Skip to content
+

Chat - Date divider

Group messages by day with inline separators inside the chat thread.

Overview

Date dividers help users orient themselves in long conversations that span multiple days by grouping messages under a day label. The date divider appears between messages whose createdAt values fall on different calendar days. It is an opt-in feature: nothing renders until you enable it, and you can also embed the component directly in custom layouts.

Enabling date dividers

Pass features={{ dateDivider: true }} to ChatBox (or to a standalone ChatMessageList) to render dividers at every day boundary:

<ChatBox adapter={adapter} features={{ dateDivider: true }} />

Once enabled, customize the rendered component with the dateDivider slot and forward props (such as a custom formatDate) through slotProps.dateDivider:

<ChatBox
  adapter={adapter}
  features={{ dateDivider: true }}
  slotProps={{
    dateDivider: {
      formatDate: (date) =>
        date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
    },
  }}
/>

formatDate receives a native Date (the message's createdAt) and can return any ReactNode. When omitted, the label defaults to date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' }) — for example May 3, 2026 in an en-US locale.

The demo below enables the feature on a conversation spanning three days — a divider appears at each day boundary:

Date divider thread

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 one is from today. A divider appears at each day boundary above.

Customizing divider placement

By default a divider renders above a message whose createdAt falls on a different UTC calendar day than the previous message's (see Overview). To group messages differently, pass a shouldShowDivider predicate through slotProps.dateDivider. It receives { message, previousMessage, index, date, previousDate } — where date/previousDate are the parsed createdAt values (null when missing or invalid) — and returns true to render a divider above the message.

Divider by week

This recipe groups messages by ISO week instead of by day, labeling each group with the Monday that starts it:

function startOfWeekIso(date: Date) {
  const d = new Date(date);
  d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 6) % 7)); // back to Monday
  return d.toISOString().slice(0, 10);
}

const shouldShowDivider = ({ date, previousDate }) =>
  date != null &&
  previousDate != null &&
  startOfWeekIso(date) !== startOfWeekIso(previousDate);
Date divider by week

MUI Assistant
MUI Assistant

Kicking off the project this week.

You
You

Same week — no new divider above me.

MUI Assistant
MUI Assistant

A new week starts here.

You
You

Still the same week as the previous message.

MUI Assistant
MUI Assistant

And another week begins.

Divider every N messages

The predicate can ignore dates entirely. This rule inserts a divider every five messages:

<ChatBox
  adapter={adapter}
  features={{ dateDivider: true }}
  slotProps={{
    dateDivider: {
      shouldShowDivider: ({ index }) => index > 0 && index % 5 === 0,
    },
  }}
/>

The label still derives from each message's own createdAt, so pair the predicate with a custom formatDate to relabel it. When a message has no createdAt, its label renders empty — guard for that case in the predicate (or in formatDate) if your data can omit timestamps.

The same hook supports any rule: for example, group by the viewer's local day instead of the default UTC day by comparing local-date strings inside the predicate.

Interactive playground

The playground below renders the divider between two messages and lets you change formatDate and the second message's createdAt:

ChatDateDivider
Day separator between message clusters — uses caption + divider tokens.

MUI Assistant

Sent lastYear

MUI Assistant

Sent today

props
formatDateenum · 3
Custom formatter for the divider label.
fixture (message data)
dayenum · 4
createdAt of the second message — drives the boundary.

See also

  • Unread marker — the other opt-in inline separator.
  • Structure — the slot reference, including the dateDivider slot row.
  • Messages — feature flags on the message list.

API

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