suiss/ui · Component
Bubble
A chat-style message bubble with variants, alignment, a tail and optional reactions.
Bubble is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
A Bubble wraps a BubbleContent, which renders the rounded message body. Add BubbleReactions inside the bubble to pin a reaction pill to its top or bottom edge. Stack bubbles in a BubbleGroup to form a conversation.
Align bubbles to the start or end of the conversation. The tail appears only on the last bubble in a run of consecutive bubbles with the same alignment, and never on the outline or ghost variants. Use Bubble for chat transcripts and assistant replies; for a full message row with avatar and metadata, see Message.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
- Copy the source into
components/ui/bubble.tsx:
- Update the import paths to match your project.
Usage
Set align="end" for messages sent by the current user and leave the default start for incoming messages.
BubbleContent renders a div by default. Render it as a button or a for tappable bubbles, such as suggested replies; these get hover and focus styles.
Use the render prop of BubbleContent to change its element.
Set asChild on BubbleContent and pass the button or a as its child.
Pass a render function to BubbleContent that returns the button or a with the props it receives.
BubbleReactions defaults to the bottom-end corner. The bubble adds margin on that side so reactions do not overlap neighboring bubbles.
Examples
Variants
Shows every variant, from default to destructive.
Conversation
An exchange of incoming muted and outgoing end-aligned bubbles.
With reactions
Pins reactions to different corners with side and align.
Interactive
Renders the content as a button.
API Reference
BubbleGroup
A vertical stack of bubbles.
Also accepts the props of React.ComponentProps<"div">.
Bubble
The positioned wrapper that sets variant and alignment.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "secondary" | "muted" | "tinted" | "outline" | "ghost" | "destructive" | "default" | Background and text color: default (primary), secondary, muted, tinted, outline, ghost (no background or padding) or destructive. |
align | "start" | "end" | "start" | Which side of the conversation the bubble sits on: start or end. |
Also accepts the props of React.ComponentProps<"div">.
BubbleContent
The rounded message body, with the tail.
Also accepts the props of useRender.ComponentProps<"div">.
BubbleReactions
A small pill for reactions, overlapping the bubble's edge.
| Prop | Type | Default | Description |
|---|---|---|---|
align | "start" | "end" | "end" | Horizontal position along the bubble edge: start or end. |
side | "top" | "bottom" | "bottom" | Which edge of the bubble the reactions overlap: top or bottom. |
Also accepts the props of React.ComponentProps<"div">.
Accessibility
- Bubbles are static content by default and contribute no focusable elements.
- When
BubbleContentrenders abuttonora, it is in the tab order and shows a focus ring. - Reactions are plain content; if they are emoji, consider adding text that screen readers can announce.
Notes
- Styling hooks:
data-slot="bubble","bubble-content","bubble-group"and"bubble-reactions", plusdata-variantanddata-alignon the bubble anddata-sideanddata-alignon reactions. - The background is set through the
--bubble-bgcustom property. Set--bubble-surfacewhen bubbles sit on a surface other than--background, so the tail and reaction ring blend in. - Bubbles are capped at 80% of the container width, except the
ghostvariant. - Bubbles also align to
endwhen inside amessageslot withdata-align="end".
Bubble lays out one message aligned to the start or end of the conversation, and BubbleContent draws the rounded bubble with an SVG tail on the aligned side. Seven variants are available: default (primary), secondary, muted, tinted, outline, ghost and destructive; outline and ghost have no tail.
BubbleGroup stacks messages and shows the tail only on the last bubble of each run from the same side, so consecutive messages read as one block. BubbleReactions pins a small reaction pill to the top or bottom edge of a bubble.











