OTTODesign System

Code

Paper Card

Storybook group: Components · Sidebar path: Components/Paper Card · Extracted 28.09.2026

Version Tag Status API
v1 <oc-paper-card-v1> Stable, allowed for generation PaperCardV1

Overview

Source: ./src/components/paper-card/Overview.mdx

Paper card

The paper card component provides a configurable card with attributes for setting the size and background color. It has slots for setting the main and footer content and an event that triggers when a property is changed.

Default variation

Story Default:

<oc-paper-card-v1>
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Configuration

The paper card is configurable, allowing you to tailor its features and appearance to your specific needs. To explore all the available options and adjust the component, use the component configurator and see the changes affect the component in real-time.

Usage guidelines

Before integrating the paper card component into your project, make sure you have correctly installed the OTTO components package. Look through the variations page for examples of possible component variations. Here, you can discover both common and specific variations that address different use cases.

Info

See the Paper card UX documentation for detailed user experience guidelines.

Accessibility

The paper card component comes with a set of built-in accessibility features to ensure a seamless experience for all users.

Configuration

Source: ./src/components/paper-card/ConfigurationV1.mdx

Paper card configuration

Configure the paper card component with the controls below and see the changes live in the preview canvas. Click the Show code button within the preview canvas to see the source code for the current component configuration.

Story Default:

<oc-paper-card-v1>
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Interactive configurator (Storybook controls); every option is listed in the API section of this file.

API v1

Source: ./src/components/paper-card/v1/PaperCardV1.API.g.mdx

Paper Card v1 API

API: <oc-paper-card-v1> (PaperCardV1)

The paper card component provides a configurable card with attributes for setting the size and background color. It has slots for setting the main and footer content and an event that triggers when a property is changed.

Attributes / properties
Attribute Type Default Required Description
size "50" | "100" "100" no Sets the size of the paper card.
elevation-level "canvas" | "stacked" | "above" | "sticky" "canvas" no Sets the elevation level of the paper card. The elevation level determines the shadow and depth of the paper card. - canvas: no shadow, paper card appears flat, to be used on frame. - stacked: shadow, paper card appears stacked, to be used on canvas. - above: shadow, paper card appears above other levels. - sticky: shadow, paper card appears above all other levels and is sticky.
background-color string undefined no Deprecated: The background-color attribute is deprecated. Please use the CSS-Variable --background-color instead.

Sets the background color of the paper card. Note that the preferred way of using colors is via design tokens instead of hex values.
base64-href string undefined no Sets the base64 encoded link target of the paper card. Use this attribute to prevent search engines from indexing the link target.
target "_blank" | "_self" | "_parent" | "_top" undefined no Sets the target attribute of the paper card.

Note Only applies when href or base64Href is set.
rel string undefined no Sets the rel attribute of the paper card.

Note Only applies when href or base64Href is set.
as-button boolean false no Determines if the paper card behaves as a button or as a link when clicked. Set to true to make the paper card behave as a button and trigger an action instead of navigating to a new page.
oc-aria-label string undefined no Sets the ARIA label of the paper card.
Slots
Slot Required Description
default no Sets the main content of the paper card. It is displayed in the paper card of size=50, and in the top part of the paper card with size=100.
primary-action no Add an empty tag to change the default behavior of the card component.

- empty a tag: the card component behaves as a link (SEO relevant) - empty button tag: the card component behaves as a button - empty div tag: for link masking when there are multiple interactive elements
footer no Sets the footer content of the paper card. This slot only applies to paper cards with size=100. Example:
<span slot="footer" href="#">My footer</a>
Events
Event Detail type Description
oc-property-change OcPaperCardV1Events["oc-property-change"] Whenever a property value changes, this event triggers. Use this event to track all property changes within the component.

Refer to the Events documentation for more information.
oc-mount { component: string; } Fired when the component is mounted to the DOM. The event is fired when the onMount hook of the component is called by the runtime.
oc-unmount { component: string; } Fired when the component is unmounted from the DOM. The event is fired when the function returned by the onMount hook of the component is called by the runtime.
CSS custom properties
Custom property Default Description
--background-color undefined Sets the background color of the paper card. Note: The preferred way of using colors is via design tokens instead of hex values.

Variations

Source: ./src/components/paper-card/VariationsV1.mdx

Variations

Listed below are the most common variations of the paper card component as well as specific component variations for different use cases.

You can explore all available options using the component configurator, adjust the component to your needs, and see the changes live in a preview canvas.

Default

Story: components-paper-card-variations--default · tags: components

The default configuration uses size=50 with an empty default and footer slot.

<oc-paper-card-v1>
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Size 50

Story: components-paper-card-variations--size-50 · tags: components

Variation with size=50 and a placeholder in the default slot.

Args: size=50, footerSlot=``

<oc-paper-card-v1 size="50">
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Story: components-paper-card-variations--size-50-with-footer · tags: components

Variation with size=50 and a placeholder in the default slot.

Args: size=50

<oc-paper-card-v1 size="50">
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Custom background color

Story: components-paper-card-variations--custom-background-color · tags: components

Variation with a custom background color set via the --background-color CSS variable using a Design Token.

Args: size=100, --background-color=var(--oc-semantic-color-hint-100)

<oc-paper-card-v1 size="100" style="--background-color: var(--oc-semantic-color-hint-100)">
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

With button behavior

Story: components-paper-card-variations--with-button-behavior · tags: components

Variation using the as-button attribute to provide button functionality and trigger an action instead of navigating to a new page.

Args: as-button=true, oc-aria-label=Card

<oc-paper-card-v1 as-button oc-aria-label="Card">
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Story: components-paper-card-variations--with-link-behavior · tags: components

The card component with a link as primary action. Search engines will detect the href.

Args: primaryActionSlot=(see snippet)

<oc-paper-card-v1>
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <!--The <a> tag should be placed inside the light DOM to improve SEO.--><a slot="primary-action" href='#' aria-label='Card'></a>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Story: components-paper-card-variations--with-masked-link-behavior · tags: components

The card component as a masked link. Search engines will not detect the href.

Args: base64-href=Iw==, oc-aria-label=Card

<oc-paper-card-v1 base64-href="Iw==" oc-aria-label="Card">
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Story: components-paper-card-variations--with-link-switch-behavior · tags: components

The card component as a link with switch behavior. Search engines will detect the href, while users receive the Base64-encoded version.

Args: base64-href=Iz92YXJpYW50PWZvbw==, primaryActionSlot=(see snippet)

<oc-paper-card-v1 base64-href="Iz92YXJpYW50PWZvbw==">
  <oc-placeholder-v1 slot="footer" variant="text" class="oc-headline-100">FOOTER SLOT PLACEHOLDER</oc-placeholder-v1>
  <!--Search engines will detect the href, while users receive the Base64-encoded version.--><a href='#' slot="primary-action" aria-label='Card'></a>
  <oc-placeholder-v1 variant="text" class="oc-headline-100">DEFAULT SLOT PLACEHOLDER</oc-placeholder-v1>
</oc-paper-card-v1>

Demo voucher

Story: components-paper-card-variations--demo-voucher · tags: components

Variation with a oc-text-field-v1 component in the default slot and a oc-button-v1 component in the footer slot.

<oc-paper-card-v1 size="100" style="--background-color: white">
  <oc-text-field-v1
    name="myName"
    value="DZ4FCQRDNCYY77BV"
    type="text"
    placeholder="Voucher Code"
  >
    Code
  </oc-text-field-v1>
  <oc-button-v1 slot="footer" variant="primary" size="100"> Einlösen</oc-button-v1>
</oc-paper-card-v1>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo voucher",
  parameters: {
    controls: {
      disabled: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    return html`
      <oc-paper-card-v1 size="100" style="--background-color: white">
        <oc-text-field-v1
          name="myName"
          value="DZ4FCQRDNCYY77BV"
          type="text"
          placeholder="Voucher Code"
        >
          Code
        </oc-text-field-v1>
        <oc-button-v1 slot="footer" variant="primary" size="100"> Einlösen</oc-button-v1>
      </oc-paper-card-v1>
    `;
  }
}

Demo discount

Story: components-paper-card-variations--demo-discount · tags: components

Demo of two variations of the paper card that are used to promote a discount.

  • The first variation uses an oc-tag-v1 component in the default slot and an oc-icon-v1 component in the footer slot.
  • The second variation uses an oc-switch-v3 component in the default slot.
<oc-paper-card-v1 size="100" style="--background-color: white">
  <oc-tag-v1 variant="sale" size="50">25% Extra</oc-tag-v1>
  <div class="oc-headline-100 oc-mt-25">Extra auf ausgewählte Artikel</div>
  <div slot="footer" class="centerItem" style="color:#007268">
    <oc-icon-v1 type="check" size="50" class="oc-mr-25"></oc-icon-v1>Angewendet
  </div>
</oc-paper-card-v1>

<oc-paper-card-v1
  size="50"
  style="--background-color: var(--oc-semantic-color-hint-100)"
  class="oc-mt-200"
>
  <div class="discountWrapper oc-gap-25">
    <div class="discountTitle">
      <div class="oc-headline-100">Jetzt 20% Extra sparen</div>
      <div class="oc-copy-75">nur bis 20.04.2034</div>
    </div>
    <oc-switch-v3 size="100" class="oc-copy-50" style="color: white;">
      <input type="checkbox" aria-label="Rabatt anwenden" />
    </oc-switch-v3>
  </div>
</oc-paper-card-v1>

<style>
  .centerItem {
    display: flex;
    place-content: center;
  }

  .discountTitle {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px 4px;
    color: white;
  }

  .discountWrapper {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
</style>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo discount",
  parameters: {
    controls: {
      disabled: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    return html`
      <oc-paper-card-v1 size="100" style="--background-color: white">
        <oc-tag-v1 variant="sale" size="50">25% Extra</oc-tag-v1>
        <div class="oc-headline-100 oc-mt-25">Extra auf ausgewählte Artikel</div>
        <div slot="footer" class="centerItem" style="color:#007268">
          <oc-icon-v1 type="check" size="50" class="oc-mr-25"></oc-icon-v1>Angewendet
        </div>
      </oc-paper-card-v1>

      <oc-paper-card-v1
        size="50"
        style="--background-color: var(--oc-semantic-color-hint-100)"
        class="oc-mt-200"
      >
        <div class="discountWrapper oc-gap-25">
          <div class="discountTitle">
            <div class="oc-headline-100">Jetzt 20% Extra sparen</div>
            <div class="oc-copy-75">nur bis 20.04.2034</div>
          </div>
          <oc-switch-v3 size="100" class="oc-copy-50" style="color: white;">
            <input type="checkbox" aria-label="Rabatt anwenden" />
          </oc-switch-v3>
        </div>
      </oc-paper-card-v1>

      <style>
        .centerItem {
          display: flex;
          place-content: center;
        }

        .discountTitle {
          display: flex;
          flex-direction: column;
          gap: 8px;
          padding: 8px 4px;
          color: white;
        }

        .discountWrapper {
          width: 100%;
          display: flex;
          align-items: center;
          justify-content: space-between;
        }
      </style>
    `;
  }
}

Demo promotion

Story: components-paper-card-variations--demo-promotion · tags: components

Demo of a promotion card that is used to promote selected sports equipment and electronics.

<oc-paper-card-v1 size="50" style="--background-color: white">
  <button slot="primary-action" aria-owns="aria123"></button>
  <div
    id="aria123"
    style="display: grid; grid-template-areas: 'image text' 'image subtext'; column-gap: 8px;"
  >
    <ofc-placeholder-v1
      style="width: 44px; height: 44px; grid-area: image;"
      variant="image"
    ></ofc-placeholder-v1>
    <div class="oc-copy-100 oc-copy--bold">
      Ausgewählte Sportgeräte und auch für Haushalt und Elektronik und noch mehr Text
    </div>
    <div class="oc-copy-50">nur bis morgen, 23:59 Uhr</div>
  </div>
  <oc-link-v2 size="100" slot="footer" as-button class="oc-secondary-action"
    >Details</oc-link-v2
  >
</oc-paper-card-v1>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo promotion",
  parameters: {
    controls: {
      disabled: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    return html`
      <oc-paper-card-v1 size="50" style="--background-color: white">
        <button slot="primary-action" aria-owns="aria123"></button>
        <div
          id="aria123"
          style="display: grid; grid-template-areas: 'image text' 'image subtext'; column-gap: 8px;"
        >
          <ofc-placeholder-v1
            style="width: 44px; height: 44px; grid-area: image;"
            variant="image"
          ></ofc-placeholder-v1>
          <div class="oc-copy-100 oc-copy--bold">
            Ausgewählte Sportgeräte und auch für Haushalt und Elektronik und noch mehr Text
          </div>
          <div class="oc-copy-50">nur bis morgen, 23:59 Uhr</div>
        </div>
        <oc-link-v2 size="100" slot="footer" as-button class="oc-secondary-action"
          >Details</oc-link-v2
        >
      </oc-paper-card-v1>
    `;
  }
}