Installation
Complete project setup first. Your configuration
must select react/radix and include your Design System ID.
pnpm exec frontfriend download bubble -f react --primitive radixReview dependencies reported by the downloader and keep your source changes in version control.
Usage
import { Bubble, BubbleContent } from "@/components/ui/bubble";
<div className="w-80">
<Bubble variant="default" align="start">
<BubbleContent>Hello! How can I help?</BubbleContent>
</Bubble>
</div>; Examples
Default
import {
Bubble,
BubbleContent,
BubbleGroup,
BubbleReactions,
} from "@/components/ui/bubble";
<div className="flex w-full max-w-sm flex-col gap-8 py-12">
<Bubble align="end">
<BubbleContent>Hey there! what's up?</BubbleContent>
</Bubble>
<BubbleGroup>
<Bubble variant="muted">
<BubbleContent>Hey! Want to see chat bubbles?</BubbleContent>
</Bubble>
<Bubble variant="muted">
<BubbleContent>
I can group messages, switch sides, and keep the whole thread easy to
scan.
</BubbleContent>
<BubbleReactions role="img" aria-label="Reaction: thumbs up">
<span>👍</span>
</BubbleReactions>
</Bubble>
</BubbleGroup>
<Bubble align="end">
<BubbleContent>Sure. Hit me with your best demo.</BubbleContent>
</Bubble>
<Bubble variant="muted">
<BubbleContent>
Yes. You are reading a demo that is demoing itself. Very meta. Very
on-brand.
</BubbleContent>
<BubbleReactions
role="img"
aria-label="Reactions: thumbs up, fire, eyes, and 2 more"
>
<span>👍</span>
<span>🔥</span>
<span>👀</span>
<span>+2</span>
</BubbleReactions>
</Bubble>
</div>; Variants
import { Bubble, BubbleContent } from "@/components/ui/bubble";
<div className="flex w-full max-w-sm flex-col gap-3 py-12">
{(
[
"default",
"secondary",
"muted",
"tinted",
"outline",
"ghost",
"destructive",
] as const
).map((variant) => (
<Bubble key={variant} variant={variant}>
<BubbleContent>{variant}</BubbleContent>
</Bubble>
))}
</div>; Reactions
import { Bubble, BubbleContent, BubbleReactions } from "@/components/ui/bubble";
<div className="flex w-full max-w-sm flex-col gap-10 py-12">
{(
[
{ side: "bottom", align: "end" },
{ side: "bottom", align: "start" },
{ side: "top", align: "end" },
{ side: "top", align: "start" },
] as const
).map((placement) => (
<Bubble key={`${placement.side}-${placement.align}`} variant="muted">
<BubbleContent>
side={placement.side} · align={placement.align}
</BubbleContent>
<BubbleReactions
side={placement.side}
align={placement.align}
role="img"
aria-label="Reaction: thumbs up"
>
<span>👍</span>
</BubbleReactions>
</Bubble>
))}
</div>; API reference
Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Radix UI.
Bubble
| Prop | Type | Default | Description |
|---|---|---|---|
align | "start" | "end" | "start" | |
variant | unknown | "default" |
BubbleContent
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false |
BubbleReactions
| Prop | Type | Default | Description |
|---|---|---|---|
align | "start" | "end" | "end" | |
side | "top" | "bottom" | "bottom" |
Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.