Message Bubble

Holds one chat message in a speech bubble.

@paneui/theme@paneui/icons@base-ui/reactclass-variance-authority
Can you move my 3 pm with Dana?
Thursday works best
Done — moved to Thursday at 3 pm. Dana accepted.
Open in Calendar →
Here’s the summary of the vendor thread: the renewal quote went up 12% because of the new seat tier, procurement wants a 2-year term to hold the price, and legal flagged the auto-renew clause in section 4.2. Finance can approve up to $18k without a committee review, so the 2-year option would need sign-off. I’d suggest replying to ask for the 1-year price with a cap on next year’s increase.
Dana joined the conversation
Couldn’t send. Tap to retry.
Draft saved

Installation

pnpm dlx shadcn@latest add @paneui/message-bubble

Usage

Composition

Examples

Tones

Sizes

Alignment and Tail

Grouped

Interactive

Collapsible

Motion

The collapsible's height transition is removed under reduced motion; interactive bubbles press to scale-98.

Accessibility

The Show more toggle is a real <button> with aria-expanded and aria-controls pointing at the clipped region. It only appears when the content overflows.

API Reference

MessageBubble

A single conversational surface. Also accepts every prop of div (useRender).

tone= "default"
"default" | "primary" | "muted" | "outline" | "destructive" | "ghost"
primary for the sender, default for replies, muted for system, outline for quiet, destructive for errors and ghost for unframed messages.
size= "default"
"default" | "sm"
Padding, radius and text size.
align
"start" | "end"
Side the bubble hugs. Inherited from Message / MessageBubbleGroup when omitted, else start.
tail= true
boolean
Tighten the bottom corner toward the sender. Ignored for ghost.
render
ReactElement | (props, state) => ReactElement
Render as another element, e.g. <a /> or <button />; the bubble becomes pressable.
PropTypeDefaultDescription
tone"default" | "primary" | "muted" | "outline" | "destructive" | "ghost""default"primary for the sender, default for replies, muted for system, outline for quiet, destructive for errors and ghost for unframed messages.
size"default" | "sm""default"Padding, radius and text size.
align"start" | "end"—Side the bubble hugs. Inherited from Message / MessageBubbleGroup when omitted, else start.
tailbooleantrueTighten the bottom corner toward the sender. Ignored for ghost.
renderReactElement | (props, state) => ReactElement—Render as another element, e.g. <a /> or <button />; the bubble becomes pressable.

MessageBubbleGroup

Stacks consecutive bubbles from one sender with joined corners. Also accepts every prop of div.

align
"start" | "end"
Side for the whole group. Inherited from Message when omitted, else start.
PropTypeDefaultDescription
align"start" | "end"—Side for the whole group. Inherited from Message when omitted, else start.
data-align
start or end.
Data attributeDescription
data-alignstart or end.

MessageBubbleCollapsible

Clips long content with a fade and a Show more toggle. Also accepts every prop of div.

collapsedHeight= 120
number
Height in px while collapsed.
defaultExpanded= false
boolean
Start expanded.
moreLabel= "Show more"
string
Toggle label while collapsed.
lessLabel= "Show less"
string
Toggle label while expanded.
PropTypeDefaultDescription
collapsedHeightnumber120Height in px while collapsed.
defaultExpandedbooleanfalseStart expanded.
moreLabelstring"Show more"Toggle label while collapsed.
lessLabelstring"Show less"Toggle label while expanded.

messageBubbleVariants

The cva function behind MessageBubble.

tone
same as MessageBubble
size
same as MessageBubble
PropTypeDefaultDescription
tonesame as MessageBubble—
sizesame as MessageBubble—

MessageSideContext

React context ("start" | "end" | null) that Message provides so nested bubbles inherit their side.