OTTODesign System

Components

Chat bubble

The chat bubble presents an individual message within a conversation, providing optional contextual details such as the sender’s name, date, and time to help users understand who said what and when.

Configurator

LiveChat bubble: variant, overline and message
Deine Bestellung ist unterwegs und voraussichtlich morgen bei dir.
HTML
<div style="display:flex;flex-direction:column"><oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-01-15T12:34">Deine Bestellung ist unterwegs und voraussichtlich morgen bei dir.</oc-chat-bubble-v1></div>

Usage

Anatomy

Hallo! Ich bin dein OTTO Service. Wie kann ich dir bei deiner Bestellung helfen?
Liveanatomy
HTML
<div class="on-frame" style="display:flex;justify-content:center;padding:40px 16px"><div style="width:300px;display:flex;flex-direction:column"><oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-01-01T12:34">Hallo! Ich bin dein OTTO Service. Wie kann ich dir bei deiner Bestellung helfen?</oc-chat-bubble-v1></div></div>

Variants

The chat bubble has the following two variants to define the message’s alignment and visual role within the conversation flow.

  • Sent: Messages are right‑aligned to reflect the user’s own output.
  • Received: Messages appear left‑aligned to represent incoming communication.

received

Hallo! Wie kann ich dir helfen?

sent

Wo ist meine Bestellung?
Livemessage variants
HTML
<oc-chat-bubble-v1 variant="received">Hallo! Wie kann ich dir helfen?</oc-chat-bubble-v1>
<oc-chat-bubble-v1 variant="sent">Wo ist meine Bestellung?</oc-chat-bubble-v1>

Overline

In addition to alignment, the component supports flexible control of the overline:

It can be fully shown/hidden or configured to show only the sender name, the time or the combination of date and time. This allows to adjust the level of contextual information for the chat while keeping the conversation clean and readable. Messages sent within the last week show the day of the week (e.g. monday). From the sixth day onwards, the display switches from the day of the week to the full calendar date.

Deine Bestellung ist unterwegs.

hidden overline

Deine Bestellung ist unterwegs.

overline with sender

Deine Bestellung ist unterwegs.

overline with time

Deine Bestellung ist unterwegs.

overline with datetime (weekday within the last week)

Deine Bestellung ist unterwegs.

overline with sender & time

Deine Bestellung ist unterwegs.

overline with sender & datetime

Liveoverline variants
HTML
<div class="on-frame" style="display:grid;grid-template-columns:minmax(0,300px) 1fr;gap:24px 40px;align-items:center;padding:24px 16px">
<oc-chat-bubble-v1 variant="received">Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">hidden overline</p>
<oc-chat-bubble-v1 variant="received" sender="OTTO Service">Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">overline with sender</p>
<oc-chat-bubble-v1 variant="received" timestamp="2026-01-01T12:34" hide-date>Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">overline with time</p>
<oc-chat-bubble-v1 variant="received" timestamp="2026-01-01T12:34">Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">overline with datetime (weekday within the last week)</p>
<oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-01-01T12:34" hide-date>Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">overline with sender &amp; time</p>
<oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-01-01T12:34">Deine Bestellung ist unterwegs.</oc-chat-bubble-v1><p class="demo-label">overline with sender &amp; datetime</p>

Behaviour

Fitting

The width of the chat bubble uses fit-content.

Deine Bestellung wurde heute an Hermes übergeben und ist voraussichtlich morgen bei dir. Super, danke!
Livefit-content
HTML
<oc-chat-bubble-v1 variant="received" sender="OTTO Service">Deine Bestellung wurde heute an Hermes übergeben und ist voraussichtlich morgen bei dir.</oc-chat-bubble-v1>
<oc-chat-bubble-v1 variant="received">Super, danke!</oc-chat-bubble-v1>

The chat bubble spans up to 80% of the chat container to the left or right side depending on the variant. When the content reaches the width threshold, the text automatically wraps onto the next line without hyphenation.

chat viewport · bubbles up to 80 %

Hallo! Deine Bestellung wurde heute an Hermes übergeben und ist voraussichtlich morgen bei dir. Super, danke! Kann ich die Lieferung auch an eine Packstation umleiten? Na klar, das geht.
Livefitting within a chat
HTML
<div class="on-frame" style="display:flex;justify-content:center;padding:24px 16px"><div style="width:100%;max-width:360px;border:1px solid #d6d6d6;border-radius:16px;overflow:hidden;background:#f0f0f0">
<div style="background:#fff;padding:12px 8px"><oc-icon-button-v3 icon="arrow-left" variant="transparent" oc-aria-label="Zurück"></oc-icon-button-v3></div>
<div style="display:flex;flex-direction:column;gap:12px;padding:16px">
  <p class="demo-label" style="text-align:center">chat viewport · bubbles up to 80 %</p>
  <oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-09-25T09:33" hide-date>Hallo! Deine Bestellung wurde heute an Hermes übergeben und ist voraussichtlich morgen bei dir.</oc-chat-bubble-v1>
  <oc-chat-bubble-v1 variant="sent" timestamp="2026-09-25T09:34" hide-date>Super, danke! Kann ich die Lieferung auch an eine Packstation umleiten?</oc-chat-bubble-v1>
  <oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-09-25T09:35" hide-date>Na klar, das geht.</oc-chat-bubble-v1>
</div>

Best practices

Deine Bestellung wurde heute an Hermes übergeben und ist voraussichtlich morgen bei dir. Super, danke! Kann ich die Lieferung auch an eine Packstation umleiten?
CautionChange the background and text colors according to our accessibility guidelines.

Accessibility

For information on accessibility, refer to the technical documentation.

Status

Implementation

Live demo

OTTO KundenserviceOnline, antwortet meist sofort
Hallo Lara! Wie kann ich dir helfen? Mein Sessel sollte heute kommen, ich sehe aber noch keine Sendungsnummer. Ich hab nachgeschaut: Dein Sessel ist bei der Spedition und kommt morgen zwischen 10 und 14 Uhr. Die Spedition ruft dich vorher an.
Nachricht
LiveReal OTTO components, rendered by the OTTO component runtime
HTML
<div class="on-frame" style="padding:32px 16px">
<div style="width:100%;max-width:390px;margin:0 auto;background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.08)">
<div style="display:flex;align-items:center;gap:8px;padding:8px"><oc-icon-button-v3 icon="arrow-left" variant="transparent" oc-aria-label="Zurück"></oc-icon-button-v3><div style="display:grid"><span class="oc-copy-100" style="font-weight:700">OTTO Kundenservice</span><span class="oc-copy-75" style="color:var(--oc-semantic-color-text-success)">Online, antwortet meist sofort</span></div></div>
<oc-divider-v1 in-flow></oc-divider-v1>
<div style="display:flex;flex-direction:column;gap:12px;padding:16px;background:var(--oc-semantic-color-background-frame,#f0f0f0)">
  <oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-09-25T09:32" hide-date>Hallo Lara! Wie kann ich dir helfen?</oc-chat-bubble-v1>
  <oc-chat-bubble-v1 variant="sent" timestamp="2026-09-25T09:33" hide-date>Mein Sessel sollte heute kommen, ich sehe aber noch keine Sendungsnummer.</oc-chat-bubble-v1>
  <oc-chat-bubble-v1 variant="received" sender="OTTO Service" timestamp="2026-09-25T09:34" hide-date>Ich hab nachgeschaut: Dein Sessel ist bei der Spedition und kommt morgen zwischen 10 und 14 Uhr. Die Spedition ruft dich vorher an.</oc-chat-bubble-v1>
<oc-chip-v3><button>Termin ändern</button></oc-chip-v3><oc-chip-v3><button>Danke, passt!</button></oc-chip-v3></div>
<div style="display:flex;align-items:center;gap:8px;padding:12px 16px"><div style="flex:1"><oc-text-field-v1 placeholder="Nachricht schreiben">Nachricht</oc-text-field-v1></div><oc-icon-button-v3 icon="paper-plane" variant="primary" oc-aria-label="Nachricht senden"></oc-icon-button-v3></div>

Code

Version Tag Status API
v1 <oc-chat-bubble-v1> Stable, allowed for generation ChatBubbleV1

Overview (v1)

Chat bubble

The chat bubble represents a single message in a chat interface. It can be styled as either a sent or received message, and can display the sender's name and timestamp. The component also allows for customization of background and text colors through CSS variables.

Default variation
DETACH TO REPLACE CONTENT
HTML
<oc-chat-bubble-v1>
<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>
</oc-chat-bubble-v1>
Configuration

The chat bubble component is available in the main styling variants sent and received. This component 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 chat bubble 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 Chat bubble UX documentation for detailed user experience guidelines.

Accessibility

The chat bubble component does not include built-in accessibility features. Sender names and timestamps are announced as plain text by screen readers before the actual content. Ensure your chat content is properly accessible for your use case.

Configuration (v1)

Chat bubble V1 configuration

Configure the chat bubble 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.

DETACH TO REPLACE CONTENT
HTML
<oc-chat-bubble-v1>
<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>
</oc-chat-bubble-v1>

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

API v1

Chat Bubble v1 API

API: <oc-chat-bubble-v1> (ChatBubbleV1)

Chat Bubble is a component that represents a single message in a chat interface. It can be styled as either a sent or received message, and can display the sender's name and timestamp. The component also allows for customization of background and text colors through CSS variables.

Attributes / properties
Attribute Type Default Required Description
variant "sent" | "received" "sent" no Sets the main styling variant of the chat bubble.
sender string undefined no Sets the sender's name, which is displayed above the chat bubble content.
timestamp string undefined no Displays the timestamp of the message when it was created, in ISO format (e.g. 2026-01-15T13:37).

This string is parsed and formatted depending on the distance to today.
hide-date boolean false no Indicates whether the date should be hidden and only the time should be displayed. Set to true to hide the date and show only the time in the timestamp.
Slots
Slot Required Description
default yes Sets the main content of the chat bubble.
Events
Event Detail type Description
oc-property-change OcChatBubbleV1Events["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 a custom background color through a CSS variable.
Note: The preferred way of using colors is via Design Tokens instead of hex values.
--text-color undefined Sets a custom text color through a CSS variable.
Note: The preferred way of using colors is via Design Tokens instead of hex values.
--custom-spacing-x undefined Sets the custom horizontal spacing of the chat bubble.
--custom-spacing-y undefined Sets the custom vertical spacing of the chat bubble.
--border-radius undefined Sets the custom border radius of the chat bubble.

Variations (v1)

Variations

Listed below are the most common variations of the chat bubble 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-chat-bubble-variations--default · tags: components, chat-bubble, 1, variations

The default chat bubble component uses the sent variant that aligns the bubble to the right.

Args: defaultSlot=<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>

DETACH TO REPLACE CONTENT
HTML
<oc-chat-bubble-v1>
<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>
</oc-chat-bubble-v1>
Received

Story: components-chat-bubble-variations--received · tags: components, chat-bubble, 1, variations

The received variant aligns the bubble to the left.

Args: defaultSlot=<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>, variant=received

DETACH TO REPLACE CONTENT
HTML
<oc-chat-bubble-v1 variant="received">
<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>
</oc-chat-bubble-v1>
Received with sender and timestamp

Story: components-chat-bubble-variations--received-with-sender-and-timestamp · tags: components, chat-bubble, 1, variations

The received variant with sender and timestamp.

Args: defaultSlot=<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>, variant=received, sender=Absender, timestamp=2026-01-01T01:01

DETACH TO REPLACE CONTENT
HTML
<oc-chat-bubble-v1 variant="received" sender="Absender" timestamp="2026-01-01T01:01">
<oc-placeholder-v1 style="height: 100px;">DETACH TO REPLACE CONTENT</oc-placeholder-v1>
</oc-chat-bubble-v1>
Demo: Custom background color

Story: components-chat-bubble-variations--demo-custom-background-color · tags: components, chat-bubble, 1, variations

Demo: Custom background color

Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf haben.
HTML
<oc-chat-bubble-v1
variant="received"
sender="Absender"
timestamp="2026-01-01T12:34"
style="--background-color: var(--oc-semantic-color-background-soft-mint)"
>Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf
haben.</oc-chat-bubble-v1
>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo: Custom background color",
  parameters: {
    controls: {
      disabled: true
    },
    chromatic: {
      hideInChromatic: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    return html`
      <oc-chat-bubble-v1
        variant="received"
        sender="Absender"
        timestamp="2026-01-01T12:34"
        style="--background-color: var(--oc-semantic-color-background-soft-mint)"
        >Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf
        haben.</oc-chat-bubble-v1
      >
    `;
  }
}
Demo: Custom background color and text color

Story: components-chat-bubble-variations--demo-custom-background-color-and-text-color · tags: components, chat-bubble, 1, variations

Demo: Custom background color and text color

Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf haben.
HTML
<oc-chat-bubble-v1
variant="received"
sender="Absender"
timestamp="2026-01-01T12:34"
style="--background-color: var(--oc-semantic-color-background-strong-blue); --text-color: var(--oc-semantic-color-text-inverted)"
>Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf
haben.</oc-chat-bubble-v1
>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo: Custom background color and text color",
  parameters: {
    controls: {
      disabled: true
    },
    chromatic: {
      hideInChromatic: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    return html`
      <oc-chat-bubble-v1
        variant="received"
        sender="Absender"
        timestamp="2026-01-01T12:34"
        style="--background-color: var(--oc-semantic-color-background-strong-blue); --text-color: var(--oc-semantic-color-text-inverted)"
        >Hier steht ein sehr langer Probetext über zwei beste Freunde, die einen tollen Chat-Verlauf
        haben.</oc-chat-bubble-v1
      >
    `;
  }
}
Demo: Chat flow

Story: components-chat-bubble-variations--demo-chat-flow · tags: components, chat-bubble, 1, variations

Demo: Chat flow with sent and received messages

<style>
  .chat-wrapper {
    max-width: 800px;
    margin: 0 auto;
    padding: 24px;
    background: #f5f5f5;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .chat-wrapper p {
    margin: 0;
  }
</style>

<div class="chat-wrapper">
  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[0]}"
  >
    <p>Hallo! Ich bin Ihr Otto Shopping Assistent. Wie kann ich Ihnen heute helfen?</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[1]}">
    <p>Hallo! Ich suche eine neue Waschmaschine für einen 2-Personen-Haushalt.</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[2]}"
  >
    <p>
      Perfekt! Für einen 2-Personen-Haushalt empfehle ich eine Waschmaschine mit 7-8 kg
      Fassungsvermögen. Haben Sie besondere Anforderungen? Zum Beispiel:
    </p>
    <ul>
      <li>Energieeffizienzklasse</li>
      <li>Spezielle Programme (z.B. Schnellwäsche, Eco-Modus)</li>
      <li>Budget</li>
    </ul>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[3]}">
    <p>
      Am wichtigsten ist mir eine gute Energieeffizienzklasse. Mein Budget liegt bei etwa 500
      Euro.
    </p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[4]}"
  >
    <p>
      Ausgezeichnet! Ich habe 3 passende Modelle mit Energieeffizienzklasse A für Sie
      gefunden:
    </p>
    <p><strong>1. Bosch Serie 6 WAU28T40</strong> - 8kg, A-Klasse, 1400 U/min - 479€</p>
    <p><strong>2. Siemens WM14N190</strong> - 7kg, A-Klasse, 1400 U/min - 449€</p>
    <p><strong>3. Miele WSD 023 WCS</strong> - 8kg, A-Klasse, 1400 U/min - 499€</p>
    <p>Welches Modell interessiert Sie am meisten?</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[5]}">
    <p>Die Bosch Serie 6 klingt interessant. Wie sind die Bewertungen?</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[6]}"
  >
    <p>
      Die Bosch Serie 6 WAU28T40 hat hervorragende Bewertungen! ⭐⭐⭐⭐⭐ 4.7 von 5 Sternen
      (824 Bewertungen)
    </p>
    <p>Kunden loben besonders:</p>
    <ul>
      <li>Sehr leiser Betrieb</li>
      <li>Gute Waschleistung</li>
      <li>SpeedPerfect-Funktion spart Zeit</li>
      <li>Niedriger Energie- und Wasserverbrauch</li>
    </ul>
    <p>Möchten Sie die Maschine in den Warenkorb legen?</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[7]}">
    <p>Ja, bitte!</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[8]}"
  >
    <p>Perfekt! Die Waschmaschine wurde in Ihren Warenkorb gelegt. 🛒</p>
    <p>
      Gute Nachrichten: Aktuell ist die Lieferung und der Altgeräte-Abtransport kostenlos! Die
      Lieferung erfolgt innerhalb von 3-5 Werktagen.
    </p>
    <p>Kann ich Ihnen sonst noch weiterhelfen?</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[9]}">
    <p>Nein, danke! Das war sehr hilfreich. 😊</p>
  </oc-chat-bubble-v1>

  <oc-chat-bubble-v1
    variant="received"
    sender="Otto Shopping AI"
    timestamp="${messageTimestamps[10]}"
  >
    <p>
      Sehr gerne! Viel Freude mit Ihrer neuen Waschmaschine. Bei Fragen stehe ich jederzeit
      zur Verfügung. Schönen Tag noch! 👋
    </p>
  </oc-chat-bubble-v1>
</div>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo: Chat flow",
  parameters: {
    controls: {
      disabled: true
    },
    chromatic: {
      hideInChromatic: true
    }
  },
  argTypes: hideControlsBadge(Metadata),
  render() {
    const now = new Date();
    const messageTimestamps = Array.from({
      length: 11
    }, (_, index) => {
      const date = new Date(now);
      date.setDate(now.getDate() - (10 - index));
      return date.toISOString().slice(0, 16);
    });
    return html`
      <style>
        .chat-wrapper {
          max-width: 800px;
          margin: 0 auto;
          padding: 24px;
          background: #f5f5f5;
          border-radius: 8px;
          display: flex;
          flex-direction: column;
          gap: 16px;
        }

        .chat-wrapper p {
          margin: 0;
        }
      </style>

      <div class="chat-wrapper">
        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[0]}"
        >
          <p>Hallo! Ich bin Ihr Otto Shopping Assistent. Wie kann ich Ihnen heute helfen?</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[1]}">
          <p>Hallo! Ich suche eine neue Waschmaschine für einen 2-Personen-Haushalt.</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[2]}"
        >
          <p>
            Perfekt! Für einen 2-Personen-Haushalt empfehle ich eine Waschmaschine mit 7-8 kg
            Fassungsvermögen. Haben Sie besondere Anforderungen? Zum Beispiel:
          </p>
          <ul>
            <li>Energieeffizienzklasse</li>
            <li>Spezielle Programme (z.B. Schnellwäsche, Eco-Modus)</li>
            <li>Budget</li>
          </ul>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[3]}">
          <p>
            Am wichtigsten ist mir eine gute Energieeffizienzklasse. Mein Budget liegt bei etwa 500
            Euro.
          </p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[4]}"
        >
          <p>
            Ausgezeichnet! Ich habe 3 passende Modelle mit Energieeffizienzklasse A für Sie
            gefunden:
          </p>
          <p><strong>1. Bosch Serie 6 WAU28T40</strong> - 8kg, A-Klasse, 1400 U/min - 479€</p>
          <p><strong>2. Siemens WM14N190</strong> - 7kg, A-Klasse, 1400 U/min - 449€</p>
          <p><strong>3. Miele WSD 023 WCS</strong> - 8kg, A-Klasse, 1400 U/min - 499€</p>
          <p>Welches Modell interessiert Sie am meisten?</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[5]}">
          <p>Die Bosch Serie 6 klingt interessant. Wie sind die Bewertungen?</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[6]}"
        >
          <p>
            Die Bosch Serie 6 WAU28T40 hat hervorragende Bewertungen! ⭐⭐⭐⭐⭐ 4.7 von 5 Sternen
            (824 Bewertungen)
          </p>
          <p>Kunden loben besonders:</p>
          <ul>
            <li>Sehr leiser Betrieb</li>
            <li>Gute Waschleistung</li>
            <li>SpeedPerfect-Funktion spart Zeit</li>
            <li>Niedriger Energie- und Wasserverbrauch</li>
          </ul>
          <p>Möchten Sie die Maschine in den Warenkorb legen?</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[7]}">
          <p>Ja, bitte!</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[8]}"
        >
          <p>Perfekt! Die Waschmaschine wurde in Ihren Warenkorb gelegt. 🛒</p>
          <p>
            Gute Nachrichten: Aktuell ist die Lieferung und der Altgeräte-Abtransport kostenlos! Die
            Lieferung erfolgt innerhalb von 3-5 Werktagen.
          </p>
          <p>Kann ich Ihnen sonst noch weiterhelfen?</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1 variant="sent" sender="Anna M." timestamp="${messageTimestamps[9]}">
          <p>Nein, danke! Das war sehr hilfreich. 😊</p>
        </oc-chat-bubble-v1>

        <oc-chat-bubble-v1
          variant="received"
          sender="Otto Shopping AI"
          timestamp="${messageTimestamps[10]}"
        >
          <p>
            Sehr gerne! Viel Freude mit Ihrer neuen Waschmaschine. Bei Fragen stehe ich jederzeit
            zur Verfügung. Schönen Tag noch! 👋
          </p>
        </oc-chat-bubble-v1>
      </div>
    `;
  }
}
Demo: Custom spacings

Story: components-chat-bubble-variations--demo-custom-spacings · tags: components, chat-bubble, 1, variations

Demo of a chat bubble component containing a custom layout with adjustable sliders for custom spacings.

<div style="display: flex; width: fit-content; ">
  <oc-chat-bubble-v1>
    <h1 class="oc-headline-200 oc-text-color-success">Hallo Sophie,</h1>
    <h1 class="oc-headline-100 oc-text-color-success">wie kann ich dir helfen?</h1>
  </oc-chat-bubble-v1>
</div>

<div style="display: flex; flex-direction: column; gap: 16px;  margin-top: 32px;">
  <div style="display: flex; gap: 16px; align-items: center;">
    <label for="horizontal-slider">Horizontal Spacing</label>
    <input
      type="range"
      name="horizontal-slider"
      id="horizontal-slider"
      min="0"
      max="64"
      value="0"
    />
    <span id="horizontal-slider-value">0px</span>
  </div>
  <div style="display: flex; gap: 16px; align-items: center;">
    <label for="vertical-slider">Vertical Spacing</label>
    <input
      type="range"
      name="vertical-slider"
      id="vertical-slider"
      min="0"
      max="64"
      value="16"
    />
    <span id="vertical-slider-value">16px</span>
  </div>
</div>

<script>
  (() => {
    const row = document.querySelector("oc-chat-bubble-v1");
    const horizontalSlider = document.getElementById("horizontal-slider");
    const horizontalSliderValue = document.getElementById("horizontal-slider-value");
    const verticalSlider = document.getElementById("vertical-slider");
    const verticalSliderValue = document.getElementById("vertical-slider-value");

    horizontalSlider.addEventListener("input", (event) => {
      const value = event.target.value + "px";
      row.style.setProperty("--custom-spacing-x", value);
      horizontalSliderValue.textContent = value;
    });

    verticalSlider.addEventListener("input", (event) => {
      const value = event.target.value + "px";
      row.style.setProperty("--custom-spacing-y", value);
      verticalSliderValue.textContent = value;
    });
  })();
</script>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo: Custom spacings",
  parameters: {
    controls: {
      disabled: true
    },
    backgrounds: {
      value: "frame"
    },
    chromatic: {
      hideInChromatic: true
    }
  },
  render: () => {
    return html`
      <div style="display: flex; width: fit-content; ">
        <oc-chat-bubble-v1>
          <h1 class="oc-headline-200 oc-text-color-success">Hallo Sophie,</h1>
          <h1 class="oc-headline-100 oc-text-color-success">wie kann ich dir helfen?</h1>
        </oc-chat-bubble-v1>
      </div>

      <div style="display: flex; flex-direction: column; gap: 16px;  margin-top: 32px;">
        <div style="display: flex; gap: 16px; align-items: center;">
          <label for="horizontal-slider">Horizontal Spacing</label>
          <input
            type="range"
            name="horizontal-slider"
            id="horizontal-slider"
            min="0"
            max="64"
            value="0"
          />
          <span id="horizontal-slider-value">0px</span>
        </div>
        <div style="display: flex; gap: 16px; align-items: center;">
          <label for="vertical-slider">Vertical Spacing</label>
          <input
            type="range"
            name="vertical-slider"
            id="vertical-slider"
            min="0"
            max="64"
            value="16"
          />
          <span id="vertical-slider-value">16px</span>
        </div>
      </div>

      <script>
        (() => {
          const row = document.querySelector("oc-chat-bubble-v1");
          const horizontalSlider = document.getElementById("horizontal-slider");
          const horizontalSliderValue = document.getElementById("horizontal-slider-value");
          const verticalSlider = document.getElementById("vertical-slider");
          const verticalSliderValue = document.getElementById("vertical-slider-value");

          horizontalSlider.addEventListener("input", (event) => {
            const value = event.target.value + "px";
            row.style.setProperty("--custom-spacing-x", value);
            horizontalSliderValue.textContent = value;
          });

          verticalSlider.addEventListener("input", (event) => {
            const value = event.target.value + "px";
            row.style.setProperty("--custom-spacing-y", value);
            verticalSliderValue.textContent = value;
          });
        })();
      </script>
    `;
  },
  argTypes: hideControlsBadge(Metadata)
}