ChatMessage
Bubble component for conversational UIs. Supports user, assistant, and system roles with distinct styling. Integrates with StreamingText for AI response animation.
Preview
Hi! I'm Sitka's design assistant. How can I help you build something today?
Can you show me the progress bar component?
Of course! The Progress Bar is available under Components → Display. It supports determinate, indeterminate (shimmer), and segmented variants with Liquid Glass styling.
• Session started at 6:50:40 PM
Streaming response
Set streaming: true on an assistant message to animate the text with StreamingText.
Role variants
user
User messages align right with accent fill.
assistant
Assistant aligns left with a subtle surface fill and border.
system
System messages use muted italic styling.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
role | "user" | "assistant" | "system" | "assistant" | Who sent the message. Determines alignment, bubble style, and default avatar. |
content | ReactNode | — | Message content. Plain strings render in a text paragraph; React nodes render as-is. |
streaming | boolean | false | When true and content is a string, renders with StreamingText typewriter animation. |
timestamp | Date | — | Optional timestamp displayed below the bubble. |
avatar | ReactNode | — | Optional custom avatar. Overrides the default robot/user/system icons. |
actions | ReactNode | — | Optional action row (copy, edit, retry) shown on hover. |
className | string | — | Custom class for the outer motion.div wrapper. |
Accessibility
- →Each message bubble must carry an accessibilityLabel combining role and content preview: 'Assistant: Hi! I'm Sitka's design assistant.'
- →The streaming animation must not announce each character — set accessibilityLiveRegion to 'polite' and only announce when streaming completes.
- →Avatar icons are purely decorative — wrap them in aria-hidden='true' unless the avatar carries semantic meaning (e.g., agent identity).
- →The timestamp must use a relative format for sighted users and an absolute format for screen readers: aria-label='Sent at 2:41 PM'.
- →Action buttons (copy, edit) must have distinct labels and not rely on icon-only recognition.