Bubble

Chat messages with sender alignment, seven treatments and an optional reactions row.

<tp-bubble>
Conversation
Default density Compact density Restart from the initial state Show the copyable source
Hi Maya, the March invoice shows two seats we removed last week. Can you check whether the credit was applied? Good catch. The credit posts on the next billing date, April 1. I've added a note to your account so it shows on the receipt. 👍

Usage

tp-bubble renders one message; tp-bubble-group stacks consecutive messages from the same sender. Your application owns delivery, sender names and reaction counts; the Bubble only presents them.

Grouping adds no conversation state or announcements.

Treatments

Variants
Default density Compact density Restart from the initial state Show the copyable source
Default Secondary Subdued Tinted Outline Ghost Message failed to send. Tap to retry.

secondary is the default. Use one treatment per sender so the conversation reads at a glance, ghost for unframed assistant text that should take the full row, and destructive for delivery failures.

Sender alignment

align is logical: end sits on the inline end and follows writing direction. Group consecutive messages so spacing reflects who is speaking, not each message.

Alignment
Default density Compact density Restart from the initial state Show the copyable source
Deploy finished for web-prod. Error rate is back under 0.1%. Thanks. I'll close the incident.

Reactions

The reactions slot accepts plain counts or real controls. reaction-side picks the top or bottom edge and reactions-align the inline edge; the two are independent. Give every reaction an accessible name.

Empty reactions have no visible surface.

Reactions
Default density Compact density Restart from the initial state Show the copyable source
The new onboarding flow is live for 10% of signups. 🎉 🔥 Nice. Let's review conversion on Friday. 👀 Can someone own the follow-up survey? Like · 3

Rich content

The default slot takes any content: paragraphs and links keep their own semantics. The message container is a named group (label, default “Message”); label="" removes the role.

Rich content
Default density Compact density Restart from the initial state Show the copyable source

Release notes for 2.4 are drafted.

Highlights: SSO for all plans, faster exports, and the new audit log. Read the draft

Long messages

Expandable message
Default density Compact density Restart from the initial state Show the copyable source

Here's the summary from this morning's incident review.

Show more

Checkout errors started at 09:12 when the payments provider rotated its signing keys. Our webhook verifier cached the old key for up to an hour.

We shortened the cache to five minutes and added an alert on signature failures. No orders were lost; 41 customers saw a retry prompt.

Put a Collapsible inside the bubble to keep long replies short in the thread. The Collapsible owns expansion and its native button; partContracts swaps the label as it opens, and partPresentation trims the trigger to fit the bubble’s padding.

Quick replies
Default density Compact density Restart from the initial state Show the copyable source
Hi Sam, your order #10482 is out for delivery. Anything I can help with? Track your package Change the delivery address Leave it with a neighbor Talk to a person

A whole bubble can be a link or a button. partContracts renders the bubble-content part as a native a or button, which keeps the bubble’s look and gives it real link or button behavior. Here the suggested replies send themselves when picked.

partContracts['bubble-content'] also supports content and render delegation for a native interactive content host; delegates must retain the supplied binding and give interactive hosts a name. A render delegate must apply its supplied bind directive to the semantic host and render the supplied content; this preserves component state and slot behavior.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptionalignalign'start' | 'end''start'The sender's side, in writing direction: end for the current user's own messages.variantvariant'default' | 'secondary' | 'subdued' | 'tinted' | 'outline' | 'ghost' | 'destructive''secondary'The message's treatment: one per sender, ghost for unframed full-width text, destructive for a failed delivery.reaction-sidereactionSide'block-start' | 'block-end''block-end'The edge, top or bottom, that the reactions sit on.reactions-alignreactionsAlign'start' | 'end''end'The inline edge the reactions line up with, independent of the message's alignment.labellabelstring'Message'The name of the message's group for assistive technology; empty removes the group role.

Slots

SlotDescriptiondefaultThe message content: text, paragraphs, links or a Collapsible for a long reply.reactionsReaction counts or reaction controls, each with an accessible name.

CSS parts

PartDescription::part(bubble-content)The framed content and the treatment of the variant.::part(bubble-reactions)The row of reactions on the edge of the message.::part(bubble-root)The message container: its alignment and its named group.

<tp-bubble-group>

Slots

SlotDescriptiondefaultThe sender's Bubbles, in order.