Bubble is installed into your project as a file you own. It takes the same props as Ant Design X's Bubble, and comes with Bubble.List, Bubble.System and Bubble.Divider attached. The kit adds no props of its own: it forwards ref and merges className, so every prop works the way the Ant Design X docs describe.
Install
npx antuikit@latest init
npx antuikit@latest add bubble
The first command installs AntuikitProvider and the theme tokens, the second adds this component.
Import
From @/components/ui/bubble, never from @ant-design/x. The file lives in your project, so the import is a path, not a package. BubbleItemType comes from the same file, for typing your items.
import { Bubble, type BubbleItemType } from "@/components/ui/bubble"
The axes
Three props that take a value from a set and decide how a message looks.
placement takes start (the default) and end. Put the reader's own messages at end. The avatar and the default footer follow it.
variant takes filled (the default), outlined, shadow and borderless. Use borderless for long AI answers that read better as page text than as a bubble.
shape takes default, round and corner. corner squares the corner on the sender's side, like a speech bubble. A borderless bubble has no outline, so it ignores shape.
Content, typing and streaming
content is a string by default. For Markdown or your own message object, type the component as Bubble<YourType> and render it with contentRender.
loading shows a three-dot indicator in place of the content. loadingRender replaces it.
typing animates the text in. true fades each chunk in, and { effect: 'typing' } gives a typewriter with a cursor. It only animates a string.
streaming tells the bubble that content is still growing. Keep it true until the last chunk arrives, or onTypingComplete fires every time the animation catches up with the stream.
Slots
Four props that take a node, or a function of (content, info) that returns one. The function form lets a role in Bubble.List render a slot per message.
avatar sits beside the bubble on the placement side.
header sits above the content, for a name or a time.
footer sits below it, for copy, retry or feedback buttons. footerPlacement moves it inside the bubble or to the other edge.
extra sits on the far side, and hides while the bubble is loading or being edited.
Bubble.List
Bubble.List renders a conversation from items. Each item needs a key and a role, and the list's role prop maps each role name to default Bubble props. An item's own props win over its role's.
{ key: "2", role: "ai", content: "Oblomov spends the morning in bed." },
9
]}
10
/>
The role names system and divider are reserved: an item with either renders Bubble.System or Bubble.Divider. Pick another name for a custom role. Give the list a height through its parent (a flex column with a fixed height) or a max-height, so it can scroll.
Events
onTyping fires on each animation step, with the text shown so far and the full text.
onTypingComplete fires once the full text is on screen, and waits for streaming to turn false.
onEditConfirm fires with the edited text, and onEditCancel fires on cancel. Set editable back to false in both.
Styling
classNames and styles take one key per part. Use them before a descendant selector: a part with a key keeps its name across versions.
1
<Bubble
2
classNames={{
3
root: "…",
4
avatar: "…",
5
body: "…",
6
header: "…",
7
content: "…",
8
footer: "…",
9
extra: "…",
10
}}
11
/>
On Bubble.List, classNames also takes scroll, bubble, system and divider. A role's or an item's own classNames win over the list's.
API Reference
Bubble
Bubble's props. Rows marked antuikit in the Version column are added by the kit.
Bubble.List
Bubble.List's props. Rows marked antuikit in the Version column are added by the kit.