Skip to content

Display

Message Bubble

A chat bubble with direction, grouping tails, sender and avatar, reply quote, reactions and delivery ticks.

<script>
  import { MessageBubble } from "@codeatlasdev/ui";
</script>

<MessageBubble direction="out" time="14:32" status="delivered">Sent it by email.</MessageBubble>

direction picks the side and colors (out uses the brand fill). Consecutive messages from one person use grouped: first, middle and last flatten the joined corners, and only single and last keep the tail and show the avatar slot (the other positions reserve its width so the column stays aligned). The delivery ticks are decorative; the state is also written as visually hidden text after the time, so a screen reader hears “14:32, Delivered” once. The bubble has no live region: the list that appends messages decides what is announced.

#248

A grouped conversation

The first bubble shows the sender, the last one the avatar and the tail.

Maria Souza
Can you send the invoice for March?
14:30
MS
I need it before the review.
14:30
Sent it by email just now.
14:32 Read

Reference #248 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Avatar, MessageBubble } from '@codeatlasdev/ui';
</script>

<div class="thread">
  <MessageBubble direction="in" grouped="first" sender="Maria Souza" time="14:30">
    {#snippet avatar()}<Avatar alt="Maria Souza" size="sm" />{/snippet}
    Can you send the invoice for March?
  </MessageBubble>
  <MessageBubble direction="in" grouped="last" time="14:30">
    {#snippet avatar()}<Avatar alt="Maria Souza" size="sm" />{/snippet}
    I need it before the review.
  </MessageBubble>
  <MessageBubble direction="out" time="14:32" status="read">Sent it by email just now.</MessageBubble>
</div>

<style>
  .thread { display: flex; flex-direction: column; gap: var(--ca-space-1); max-inline-size: 32rem; }
</style>
#249

Delivery status

pending, sent, delivered and read; read ticks use the info color.

pending
09:41 Sending
sent
09:41 Sent
delivered
09:41 Delivered
read
09:41 Read

Reference #249 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { MessageBubble } from '@codeatlasdev/ui';

  const states = ['pending', 'sent', 'delivered', 'read'] as const;
</script>

<div class="thread">
  {#each states as status}
    <MessageBubble direction="out" time="09:41" {status}>{status}</MessageBubble>
  {/each}
</div>

<style>
  .thread { display: flex; flex-direction: column; gap: var(--ca-space-2); max-inline-size: 32rem; }
</style>
#250

Quote and reactions

The quote slot renders a reply preview; reactions overlap the bottom edge.

You Meeting moved to 3 pm
Carlos
Perfect, see you there.
18:02
👍2🎉

Reference #250 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { MessageBubble } from '@codeatlasdev/ui';
</script>

<div class="thread">
  <MessageBubble
    direction="in"
    sender="Carlos"
    time="18:02"
    reactions={[{ emoji: '👍', count: 2, mine: true }, { emoji: '🎉' }]}
  >
    {#snippet quote()}
      <strong>You</strong>
      <span>Meeting moved to 3 pm</span>
    {/snippet}
    Perfect, see you there.
  </MessageBubble>
</div>

<style>
  .thread { max-inline-size: 32rem; padding-block-end: var(--ca-space-4); }
</style>

Props

PropTypeDefaultDescription
direction'in' | 'out''in'Side and color.
grouped'single' | 'first' | 'middle' | 'last''single'Position in a run of bubbles from one sender; controls the tail and spacing.
senderstring–Name above the text, for incoming single or first bubbles.
avatarSnippet–Avatar slot beside incoming bubbles (single and last).
quoteSnippet–Reply preview shown at the top of the bubble.
reactions{ emoji: string; count?: number; mine?: boolean }[]–Reaction chips under the bubble.
timestring–Footer time text.
status'pending' | 'sent' | 'delivered' | 'read'–Delivery ticks for outgoing bubbles.
footerSnippet–Extra footer content before the time.
childrenSnippet–Message body.