Skip to content
+

Chat - Layout

Compose conversation and thread panes in the chat surface, with full control over layout and responsive behavior.

Overview

ChatLayout arranges a conversation pane and a thread pane in the chat surface. The surrounding runtime setup is delegated to ChatProvider; you supply the pane contents as children, and ChatLayout only assigns each child to a pane and positions it.

Composition structure

The most common ChatLayout composition looks like this:

ChatLayout
  ChatConversationList              ← sidebar with conversation entries
  ChatConversation                  ← thread shell, derives the active conversation
    ChatConversationHeader          ← header bar with divider styling
      ChatConversationTitle         ← conversation name
      ChatConversationSubtitle      ← secondary line (participants, presence, etc.)
      ChatConversationHeaderActions ← action area (archive, mute, context menu)
    ChatMessageList                 ← scrollable message area
      ChatMessageGroup              ← groups consecutive same-author messages
        ChatMessage                 ← individual message row
          ChatMessageAvatar         ← author avatar
          ChatMessageContent        ← bubble + inner part renderers
          ChatMessageMeta           ← timestamp, status indicator
          ChatMessageActions        ← hover action menu
    ChatComposer                    ← composer form (border-top)
      ChatComposerTextArea          ← auto-resizing textarea
      ChatComposerToolbar           ← button row
        ChatComposerAttachButton
        ChatComposerSendButton

ChatLayout is exported from @mui/x-chat/headless; every component below it in the tree is exported from @mui/x-chat.

Two-pane layout

The default composition renders the conversation list and the active thread side by side. Select a conversation in the sidebar to switch the thread:

MUI Assistant
Component questions
Which component handles the composer?
2
MUI Assistant
Theme customization
How do I override the bubble color?
MUI Assistant
Slot overrides
Replacing the send button slot
Component questions

Which component handles the composer?

Alice Chen
Alice Chen

Which component should I use for the message input area?

MUI Assistant
MUI Assistant

The composer is handled by the ChatBox automatically. You can override it with slots.composer.

Alice Chen
Alice Chen

And what about slotProps for passing sx to the input?

Sizing the panes

ChatLayout wraps each pane in a slot: conversationsPane and threadPane (plus root for the flex container). By default the thread pane flexes to fill the remaining width. Use slotProps to set a fixed sidebar width:

<ChatLayout
  slotProps={{
    conversationsPane: { style: { width: '280px', flex: '0 0 280px' } },
  }}
>

Each pane slot receives a pane owner state ('conversations' or 'thread'), so a custom slot component can style both panes from one implementation.

Thread-only mode

When your application manages conversations externally, render only the thread pane inside ChatLayout. The demo below keeps the provider, message list, and composer but omits the conversation pane:

Material UI chat

Styled with your active MUI theme

MUI Assistant
MUI Assistant

Hello! I am styled using your active Material UI theme. Try sending a message.

You
You

Great — the bubble colors come from palette.primary and the typography from the theme.

In thread-only mode the active conversation fills the entire ChatLayout container.

Full recomposition

Because ChatLayout only decides where panes go, you can assemble the thread from individual Material UI components directly. Use this approach to insert additional UI between the header and the message list, or to move controls within the thread pane.

The example below shows a fully assembled thread pane that doesn't rely on the layout defaults bundled into ChatBox, the all-in-one component:

import {
  ChatConversation,
  ChatConversationHeader,
  ChatConversationTitle,
  ChatConversationSubtitle,
  ChatConversationHeaderActions,
  ChatMessageList,
  ChatMessageGroup,
  ChatComposer,
  ChatComposerTextArea,
  ChatComposerToolbar,
  ChatComposerSendButton,
} from '@mui/x-chat';
import Box from '@mui/material/Box';

function CustomThread() {
  return (
    <ChatConversation sx={{ height: '100%' }}>
      <ChatConversationHeader>
        <ChatConversationTitle />
        <ChatConversationSubtitle />
        <Box sx={{ flex: 1 }} />
        <ChatConversationHeaderActions />
      </ChatConversationHeader>

      {/* Custom pinned notice between header and messages */}
      <Box
        sx={{
          px: 2,
          py: 0.75,
          bgcolor: 'warning.light',
          color: 'warning.contrastText',
          fontSize: 'caption.fontSize',
        }}
      >
        Responses are AI-generated. Verify before acting.
      </Box>

      <ChatMessageList
        renderItem={({ id, index }) => (
          <ChatMessageGroup index={index} messageId={id} />
        )}
      />

      <ChatComposer>
        <ChatComposerTextArea placeholder="Type a message…" />
        <ChatComposerToolbar>
          <ChatComposerSendButton />
        </ChatComposerToolbar>
      </ChatComposer>
    </ChatConversation>
  );
}
Material UI chat

Styled with your active MUI theme

Responses are AI-generated. Verify before acting.
MUI Assistant
MUI Assistant

Hello! I am styled using your active Material UI theme. Try sending a message.

You
You

Great — the bubble colors come from palette.primary and the typography from the theme.

Wrap CustomThread with a ChatProvider from @mui/x-chat/headless to wire runtime state to your adapter.

Pane assignment

ChatLayout inspects its direct children to decide which pane each one belongs to. ChatConversationList is assigned to the conversations pane and ChatConversation to the thread pane automatically.

If you wrap a pane child in another component (styled(), React.memo(), or a custom wrapper), ChatLayout can no longer identify it. Unidentified children fall back to positional assignment: a single child fills the thread pane, and with several children the unidentified ones fill the conversations pane first, then the thread pane. Instead of relying on this fallback, set the pane prop on the direct child explicitly:

<ChatLayout>
  <MySidebar pane="conversations" />
  <MyThread pane="thread" />
</ChatLayout>

In development, ChatLayout warns in the console when it can identify some children but not others.

Responsive layout

ChatLayout does not impose breakpoint behavior. You decide when to show both panes, when to show only the conversation list, and when to show only the active thread.

Drag the slider below to switch the same composition between:

  • a two-pane layout above 600px
  • a single-pane conversation list or thread below 600px

The demo below keeps the logic explicit so you can swap it for route-based navigation, a drawer, or any other responsive pattern:

Container width

720px

MUI Assistant
Component questions
Which component handles the composer?
2
MUI Assistant
Theme customization
How do I override the bubble color?
MUI Assistant
Slot overrides
Replacing the send button slot
Component questions

Which component handles the composer?

Alice Chen
Alice Chen

Which component should I use for the message input area?

MUI Assistant
MUI Assistant

The composer is handled by the ChatBox automatically. You can override it with slots.composer.

Alice Chen
Alice Chen

And what about slotProps for passing sx to the input?

When collapsing to a single pane, keep the navigation accessible: label the conversation list (for example aria-label="Conversations") and give the narrow-mode back control an explicit label such as aria-label="Back to conversations", as the demo above does.

Explicit responsive logic keeps narrow-mode transitions straightforward to customize.

Set explicit dimensions on the parent element that wraps ChatLayout:

<Box sx={{ height: 500 }}>
  <ChatLayout>{/* conversation pane + thread pane */}</ChatLayout>
</Box>

For the unstyled primitives behind this page, see the headless layout documentation.

API

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