
Default chat bubbles inherit palette.background.paper and divider automatically.
Render conversation history as a virtualized, grouped, auto-scrolling message list.
Toggle role, status, density, and grouping on a single ChatMessage bubble:

Default chat bubbles inherit palette.background.paper and divider automatically.
ChatMessageGroup collapses consecutive messages from the same author into a single visual cluster:

Three quick notes on theming.
First—the avatar only renders for the first message in a group.
Second—bubbles tighten vertically when grouped.
ChatMessageList virtualizes rendering, manages auto-scroll, and can insert opt-in dividers between days:

Message 8 from MUI Assistant.
Message 7 from Alice Chen.
Message 6 from You.

Message 5 from MUI Assistant.
Message 4 from Alice Chen.
Message 3 from You.

Message 2 from MUI Assistant.
Message 1 from Alice Chen.
ChatMessage data modelEvery message in the chat system is represented by the ChatMessage interface:
import type { ChatMessage } from '@mui/x-chat/headless';
A ChatMessage has the following shape:
| Field | Type | Description |
|---|---|---|
id |
string |
Unique identifier for the message |
role |
ChatRole |
'user', 'assistant', or 'system' |
parts |
ChatMessagePart[] |
Content parts that make up the message body (text, files, tools, etc.) |
status |
ChatMessageStatus |
Delivery lifecycle: 'pending', 'sending', 'streaming', 'sent', 'read', 'error', or 'cancelled' |
author |
ChatUser |
The author payload used for inline identity data and member matching |
createdAt |
string |
ISO 8601 timestamp when the message was created |
updatedAt |
string |
ISO 8601 timestamp when the message was last updated |
editedAt |
string |
ISO 8601 timestamp if the message was edited |
conversationId |
string |
The conversation this message belongs to |
metadata |
ChatMessageMetadata |
Extensible metadata object for custom data |
author.id is the canonical identity key for message rendering.
If you pass members, currentUser, or active conversation participants, chat components use that id to enrich missing display names and avatars at render time.
If your message model stores author identity somewhere else, provide getMessageAuthorId, getMessageAuthorDisplayName, and getMessageAuthorAvatarUrl on ChatProvider, ChatRoot, or ChatBox to map that data into the built-in message primitives.
The parts array is the core content model.
Each part has a type discriminant that determines how it renders:
| Part type | Description |
|---|---|
text |
Plain or markdown text content |
reasoning |
Model reasoning / chain-of-thought text |
file |
An attached file (image, document, etc.) |
source-url |
A URL citation |
source-document |
A document citation |
tool |
A tool call invocation and its result |
step-start |
A visual separator between agentic steps |
This part-based model means a single message can contain mixed content—for example, a text explanation followed by a code block and a source citation.
Messages progress through a status lifecycle:
pending → sending → streaming → sent → read
\→ error
\→ cancelled
import { ChatMessageList, ChatMessageGroup, ChatMessage } from '@mui/x-chat';
Inside ChatBox, the message list renders a subtree of themed components:
ChatMessageList ← scrollable container
MessageListDateDivider ← date separator between message groups (opt-in)
ChatMessageGroup ← groups consecutive same-author messages
ChatMessage ← individual message row
ChatMessageAvatar ← author avatar
ChatMessageContent ← message bubble with part renderers
ChatMessageMeta ← timestamp, delivery status
ChatMessageActions ← hover action buttons
The ChatMessageList component is the scrollable region that renders conversation history.
It manages scroll behavior, overflow, padding, and a thin scrollbar by default.
Consecutive messages from the same author are grouped together into a ChatMessageGroup.
Within a group, only the first message displays the avatar, reducing visual repetition and making the conversation easier to scan.
If no display name or avatar resolves for a message author, the UI omits those affordances instead of falling back to the role name.
See Message appearance for grouping configuration and demos.
When consecutive messages span different calendar dates, the message list can render a date divider between them.
Dividers are disabled by default—enable them with the dateDivider feature flag:
<ChatBox adapter={adapter} features={{ dateDivider: true }} />
See Date divider and Message appearance for customization.
The message list automatically scrolls to the bottom when the user sends a new message, when new assistant messages arrive, and during streaming.
See Scrolling for buffer configuration and scroll-to-bottom affordance.
The message list is a single Tab stop: a roving tabindex over the role="article" messages keeps only one message in the tab order at a time, so tabbing through the page never walks every message.
role="log" polite live region, and a visually hidden role="status" region announces streaming transitions ("Assistant is responding" / "Response complete") exactly once each.Tab into the list (a single stop), Arrow Up/Down between messages, Enter to drill into the focused message's links and buttons, Escape to come back, Tab onward to the composer.
Set enableRovingFocus={false} on the message list to opt out, and use the useMessageContentTabIndex() hook from @mui/x-chat/headless to let custom interactive content participate.
See the complete model—including the drill-in lifecycle, per-list focus memory, and locale keys—on the Accessibility page and in Message list—Accessibility.
When building a custom layout outside of ChatBox, render ChatMessageList inside ChatConversation within a ChatProvider.
The demo below isolates the message surface with only the provider, an active conversation scope, a bounded frame, and the message list composition:
Hello! I am styled using your active Material UI theme. Try sending a message.
Great — the bubble colors come from palette.primary and the typography from the theme.
Each slot inside the ChatMessage row has its own playground—iterate on a single surface at a time.
The author avatar slot—falls back to initials when no avatarUrl is set.

Avatar preview message.
Displays the author name above grouped messages.
The bubble interior—renders markdown, code fences, and tool or source parts.

Markdown is rendered automatically:
Inline code works too.
External timestamp and delivery status, used by compact bubbles.
Meta preview message.
Telegram-style timestamp and status flowing inside the bubble.
Inline meta sits at the bottom-right of this bubble.
See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.