AI
BubbleAI
A rounded container for short messages, used for what people write in a chat with an assistant.
npx prodular-ui add bubbleVariants
Muted is the default. The others are for messaging between people.
import { Bubble, BubbleContent, BubbleGroup } from "@/components/ui/bubble"
export default function BubbleVariants() { return ( <div className="flex w-full max-w-md flex-col gap-3"> <Bubble align="end"> <BubbleContent>Muted, the default for what people write to the assistant.</BubbleContent> </Bubble> <Bubble variant="outline"> <BubbleContent>Outline, for quoted or forwarded text.</BubbleContent> </Bubble> <Bubble variant="tinted" align="end"> <BubbleContent>Tinted, for the message you are replying to.</BubbleContent> </Bubble> <Bubble variant="default" align="end"> <BubbleContent>Default, a solid primary fill for messaging products.</BubbleContent> </Bubble> <BubbleGroup> <Bubble variant="destructive"> <BubbleContent>This message could not be sent. Check your connection and try again.</BubbleContent> </Bubble> </BubbleGroup> </div> )}Groups and reactions
Consecutive bubbles from one author sit in a BubbleGroup. BubbleContent can render as a button.
import { ThumbsUpIcon } from "lucide-react"
import { Bubble, BubbleContent, BubbleGroup, BubbleReactions } from "@/components/ui/bubble"import { Message, MessageContent, MessageHeader, MessageMeta } from "@/components/ui/message"
export default function BubbleReactionsDemo() { return ( <div className="flex w-full max-w-md flex-col gap-6"> <Message from="system"> <MessageContent className="gap-1"> <MessageHeader> Daniel Ortiz <MessageMeta>11:02</MessageMeta> </MessageHeader> <BubbleGroup> <Bubble> <BubbleContent>PO 4471 is approved.</BubbleContent> </Bubble> <Bubble className="mb-3"> <BubbleContent>Copilot can release the Northbeam payment now.</BubbleContent> <BubbleReactions align="start" className="gap-1 text-muted-foreground"> <ThumbsUpIcon className="size-3.5" /> <span className="text-xs tabular-nums">2</span> </BubbleReactions> </Bubble> </BubbleGroup> </MessageContent> </Message> <Message from="user"> <MessageContent> <Bubble align="end" variant="outline"> <BubbleContent render={<button type="button" />}>Release payment</BubbleContent> </Bubble> </MessageContent> </Message> </div> )}Anatomy
<Bubble align="end"> <BubbleContent>What is our runway?</BubbleContent></Bubble>Guidance
Use it when
- For user messages in an assistant chat, and for every message in chat between people.
- BubbleContent with render={<button />} for quick replies that send when pressed.
Avoid
- Assistant answers. Render those with Response directly in the message.
- The default primary fill in assistant chats. It competes with the answer.
Rules for AI agents
Published in llms-full.txt and the registry, so coding agents follow them when they build with this component.
- Use the muted variant with align="end" for user messages in AI chat.
- Keep bubbles under about 80% of the thread width. They do this by default.
- Use destructive only for a message that failed to send, and offer a retry next to it.
API
Bubble
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "muted" | "default" | "secondary" | "tinted" | "outline" | "ghost" | "destructive" | "muted" | Fill and border. |
| align | "start" | "end" | "start" | Side of the thread. |
BubbleContent
| Prop | Type | Default | Description |
|---|---|---|---|
| render | ReactElement | Render as a button or link for interactive bubbles. |
BubbleReactions
| Prop | Type | Default | Description |
|---|---|---|---|
| side / align | "top" | "bottom", "start" | "end" | Where reactions overlap the bubble. |