Message Bubble

Pro

Chat bubbles in six styles with grouping, swipe-to-reply and long-press actions. Drag the thread to reveal times, hold a message to react, and watch read ticks update in place.

Preview

Installation

npx @lumioui/cli add pro/message-bubble

Usage

import { MessageBubble, MessageBubbleGroup } from "@/components/ui/message-bubble/message-bubble";
<MessageBubble />

Also exported: MessageBubbleGroup.

Examples

Chat

A 1:1 thread between climbing friends (chat → green).

Support thread

An airline support thread in ink, read as one conversation: the agent speaks in soft bubbles, the rebooked flight is pinned as a tint card, an aside drops to ghost, your replies are solid.

API reference

MessageBubble

Prop Type Default
variant MessageBubbleVariant

Bubble style. Default "soft".

"soft"
align MessageBubbleAlign

Which side. Default "start".

"start"
animateIn boolean

Play an entrance animation when mounted. Default false.

false
timestamp string

Timestamp shown inside the bubble, next to the delivery ticks.

—
time string

Time revealed when the thread is swiped left (MessageBubbleGroup).

—
sender string

Sender name — exposed to screen readers, not rendered.

—
onPress () => void

Press handler — bubbles can be tappable (e.g. retry a failed send).

—
onReply () => void

Swipe right to reply. Commits on release past the line.

—
onLongPress () => void

Plain long-press callback (lift + your own UI). Ignored when the built-in reactions / actions are enabled.

—
sameAsPrev boolean

Previous bubble is from the same sender — tightens the joined corner. Inferred inside MessageBubbleGroup.

false
sameAsNext boolean

Next bubble is from the same sender. Inferred inside MessageBubbleGroup.

false
tail boolean

Draw the tail. Inferred inside MessageBubbleGroup (last of a run, solid and soft only); off by default outside one.

false
tailColor string

Tail colour when you restyle the bubble's fill with className.

—
enableSwipeReply boolean

Enable swipe-to-reply. Default true when onReply is set.

—
status MessageBubbleStatus

Delivery state — swaps in place: sending dots → sent → delivered → read. "sending" also holds the fill dim; "failed" flickers once.

—
sendFrom MessageBubbleOrigin

Composer text rect (measureInWindow) the words lift out of. Mount only.

—
reaction string | null

Your reaction (controlled). Enables the long-press reaction bar + chips.

—
defaultReaction string | null

Your initial reaction (uncontrolled).

—
onReact (emoji: string | null) => void

Fires when your reaction changes (null = taken back).

—
reactionCounts Record<string, number>

Everyone else's reactions, by emoji.

—
reactionSet ReactionOption[]

Emojis offered in the bar.

—
onCopy () => void

Adds "Copy" to the long-press menu.

—
onDelete () => void

Adds "Delete" to the long-press menu.

—
actions ReactionAction[]

Extra long-press menu rows.

—
className string —
textClassName string —
children React.ReactNode —

MessageBubbleGroup

Prop Type Default
spacing "compact" | "default"

Spacing between bubbles. Default "compact".

"compact"
revealTimes boolean

Swipe the thread left to reveal each bubble's time. Default true.

true
className string —
children React.ReactNode —