Skip to content
+

Chat - Message appearance

Control the visual presentation of messages—grouping, date dividers, avatars, timestamps, and layout variants.

This page covers the visual aspects of how messages are displayed in the message list. See Message parts for how each message's content — text, code, files — is rendered.

Message groups

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.

By default, all consecutive messages from the same author are grouped together, regardless of how much time passes between them. To split groups by time, pass createTimeWindowGroupKey(windowMs) (from @mui/x-chat/headless; the window defaults to 5 minutes) as the group's groupKey through slotProps.messageGroup. The demo below uses a 1-minute window:

Message grouping demo

Custom grouping window

You
You

First message from the user.

Second message, sent 30 seconds later. Same group because the window is 1 minute.

You
You

Third message, sent 2 minutes after the first. This starts a new group.

MUI Assistant
MUI Assistant

With createTimeWindowGroupKey(60 000), consecutive messages from the same author are grouped only when they are less than 1 minute apart. The avatar appears only on the first message in each group.

By default, a new group starts when:

  • The author identity changes (author ID, falling back to role when no explicit author ID exists).
  • With createTimeWindowGroupKey, a new group also starts when the gap to the previous message exceeds the configured window.

Date dividers

When consecutive messages span different calendar dates, a date divider can be rendered between them. The divider shows a localized date string and is styled as a centered label with horizontal rules. Dividers are disabled by default—enable them with features={{ dateDivider: true }}.

The demo below enables the feature and customizes the date format through slotProps:

Date divider demo

Custom date formatting

MUI Assistant
MUI Assistant

Here is a message from two days ago.

You
You

And this one is from yesterday.

MUI Assistant
MUI Assistant

This message is from today. Notice the short date format in the dividers above.

Date dividers render with role="separator" and are not focusable; message rows remain individually focusable — see Accessibility for the focus model.

Avatars

The ChatMessageAvatar component renders the author's avatar for the first message in each group. Avatar resolution follows the same rules as the built-in message primitives:

  • getMessageAuthorAvatarUrl(message) when provided
  • otherwise message.author?.avatarUrl
  • otherwise a matching currentUser, members, or active-conversation participant entry resolved by author id

The avatar is omitted entirely (the component returns null, no placeholder) in two cases: for every message after the first in a group, and for the first message when no avatarUrl resolves and no custom messageAvatar slot is provided.

ChatMessageAvatar
Author avatar slot—falls back to initials when no avatarUrl is set.

MUI Assistant
MUI Assistant

Avatar preview message.

fixture (message data)
roleenum · 2
chrome provider
ChatChrome.variantenum · 2

Timestamps and metadata

Two meta components exist. ChatMessageInlineMeta (default variant) renders the timestamp, delivery status (sent/read icons), and an "edited" label inside the bubble, anchored to its bottom corner — it is hidden while the message is streaming. ChatMessageMeta (compact variant) renders the same information — plus a streaming progress bar while the message streams — outside the bubble. Both derive the timestamp from createdAt and the edited label from editedAt.

The default variant renders inline meta inside the bubble:

ChatMessageInlineMeta
Telegram-style timestamp + status that flows inside the bubble.

You

Inline meta sits at the bottom-right of this bubble.

fixture (message data)
roleenum · 2
statusenum · 3

The compact variant renders external meta beside the message:

ChatMessageMeta
External meta (timestamp + delivery status) used by compact bubbles.

Meta preview message.

fixture (message data)
roleenum · 2
statusenum · 3
chrome provider
ChatChrome.variantenum · 2

Component anatomy

Inside ChatBox, the message list renders this component tree:

ChatMessageList                     ← scrollable container
  ChatDateDivider                   ← date separator between groups (opt-in)
  ChatMessageGroup                  ← groups consecutive same-author messages
    ChatMessage                     ← individual message row
      ChatMessageAvatar             ← author avatar
      ChatMessageContent            ← message bubble with part renderers
        ChatMessageInlineMeta       ← timestamp/status/edited inside the bubble (default variant; hidden while streaming)
      ChatMessageMeta               ← external meta (compact variant only)
      ChatMessageError              ← error card when message status is "error"
      ChatMessageActions            ← hover action buttons

Compact variant

Set variant="compact" on ChatBox to switch to a dense, messenger-style layout with no bubbles, left-aligned messages, and group header timestamps. In the compact layout the inline meta is replaced by the external ChatMessageMeta rendered beside the message (use the messageMeta slot to customize it; in the default variant use messageInlineMeta instead).

Team standup

Daily sync

MUI Assistant
MUI Assistant

Good morning! Here is the agenda for today.

We need to review the sprint progress and plan next steps.

You
You

Sounds good. I finished the variant feature yesterday.

The compact layout is ready for review.

MUI Assistant
MUI Assistant

Great work! The compact variant removes message bubbles and aligns everything to the left — perfect for dense message feeds.

See Variants and density for details.

Density

The density prop controls the vertical spacing between messages independently of the variant. Three values are available: compact, standard (default), and comfortable.

Design review

UI team

MUI Assistant
MUI Assistant

Hey! I just pushed the updated mockups for the settings page.

Let me know what you think about the new spacing.

You
You

Looks great! The layout feels much more balanced now.

One thing: can we increase the gap between the sections?

MUI Assistant
MUI Assistant

Sure, I will add more vertical breathing room. Give me 10 minutes.

You
You

Perfect, take your time!

See Variants and density for details.

Slots

ChatBox exposes the following slots for the message area (composer and conversation-list slots are covered on their own pages):

Slot Component Description
messageList ChatMessageList Scrollable list container (wrapper-only — default rows render inside)
messageGroup ChatMessageGroup Per-author group wrapper around consecutive messages
dateDivider ChatDateDivider Date separator between groups (requires features.dateDivider)
unreadMarker ChatUnreadMarker "New messages" marker (requires features.unreadMarker)
messageRoot ChatMessage Styled root of the message row (wrapper-only)
messageAvatar ChatMessageAvatar Author avatar — pass null to hide it and collapse the avatar track
messageContent ChatMessageContent Message bubble with part renderers
messageMeta ChatMessageMeta External meta (compact variant): timestamp, delivery status, streaming progress, edited label
messageInlineMeta ChatMessageInlineMeta Inline meta inside the bubble (default variant): timestamp, delivery status, edited label
messageError ChatMessageError Error card under the bubble when message.status is error
messageActions ChatMessageActions Hover actions row
messageAuthorName ChatMessageAuthorLabel Author name label rendered by the group wrapper

See also

API

See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.