Skip to content
+

Chat - Look and feel

Change colors, layout style, density, and typography—from quick props to full brand theming.

Live playground

The same ChatBox re-themes itself when you swap the layout variant, density, primary color, or border radius—every change comes from a single Material UI theme and two top-level props (variant and density):

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.

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?

Marco Diaz
Marco Diaz

How do I change the user message bubble color from primary to something custom?

MUI Assistant
MUI Assistant

Use createTheme with a custom palette.primary, or use slots.content to replace the bubble entirely.

Priya Singh
Priya Singh

Use slots.send to replace the send button with any React component.

You
You

That makes it easy to swap in a Fab or an IconButton from MUI.

PropsEvery change re-themes the live chat on the left.
variant
density

palette.primary.main
shape.borderRadius12px

Choosing a layout style

The variant prop controls how messages and the composer are arranged:

// Bubbles—colored message bubbles, right-aligned for user (WhatsApp, Telegram)
<ChatBox adapter={adapter} variant="default" />

// Flat—no bubbles, stacked messages with inline sender info (Slack, ChatGPT, Claude)
<ChatBox adapter={adapter} variant="compact" />

The same conversation rendered with each variant—default uses colored bubbles with own messages on the trailing edge; compact drops the bubble and shows the author inline:

variant="default"
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.

variant="compact"
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.

Press Enter to start editing

The demo below shows how the same variant prop drives the composer's two stock layouts:

variant="default"
Stacked layout — attachment list, textarea, then toolbar with attach + send.
variant="compact"
Inline layout — attach button, textarea and send button share a single row.

Choosing a density

The density prop controls vertical spacing between messages:

<ChatBox adapter={adapter} density="compact" />     // Tight spacing
<ChatBox adapter={adapter} density="standard" />    // Default
<ChatBox adapter={adapter} density="comfortable" /> // Spacious

standard is the default when the prop is omitted.

density="compact"
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.

density="standard" (default)
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.

density="comfortable"
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.

Press Enter to start editing

Message states

ChatMessage adapts to the role and status it reads from the store—no extra props required:

role="assistant" — status="sent"
MUI Assistant
MUI Assistant

Default assistant bubble — uses palette.grey[100] (light) / palette.grey[800] (dark).

role="user" — status="sent"
You
You

Outgoing user bubble — uses palette.primary.main.

role="assistant" — status="streaming"
MUI Assistant
MUI Assistant

Streaming bubble — animates while the assistant is typing…

role="assistant" — status="error"

This message failed to send.

Applying one-off styles with sx

Apply one-off styles directly on ChatBox:

<ChatBox
  adapter={adapter}
  sx={{
    height: 500,
    width: '100%',
    borderRadius: 2,
    border: '1px solid',
    borderColor: 'divider',
  }}
/>

Theme component overrides

For global style rules, use createTheme with component keys—chat text inherits theme.typography, so a fontFamily swap re-fonts the whole surface. Import '@mui/x-chat/themeAugmentation' for TypeScript autocomplete:

import type {} from '@mui/x-chat/themeAugmentation';

const theme = createTheme({
  typography: { fontFamily: '"Inter", sans-serif' },
  components: {
    MuiChatBox: {
      styleOverrides: {
        root: ({ theme }) => ({
          border: '1px solid',
          borderColor: theme.palette.divider,
        }),
      },
    },
    MuiChatMessage: {
      styleOverrides: {
        bubble: ({ theme: t }) => ({
          borderRadius: t.shape.borderRadius * 3,
        }),
      },
    },
  },
});

For dark mode, CSS class injection, and the full override-key list, see Material UI customization.

Styling internal slots

Style any internal subcomponent without replacing it:

<ChatBox
  slotProps={{
    composerInput: { placeholder: 'Ask anything...' },
    composerSendButton: { sx: { borderRadius: 6 } },
  }}
/>

Both techniques applied to a live ChatBox—the theme override rounds every bubble, and slotProps restyles the send button and placeholder:

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.

To replace subcomponents entirely, see Slot overrides.

CSS class names

Inject custom class names or use the built-in constants for CSS targeting:

import { chatBoxClasses } from '@mui/x-chat';

// Class constants: chatBoxClasses.root, chatBoxClasses.layout,
//                  chatBoxClasses.conversationsPane, chatBoxClasses.threadPane

<ChatBox classes={{ root: 'my-chat-root', layout: 'my-chat-layout' }} />;

Tailwind CSS

Prefer to bring your own CSS instead of the Material UI theme? Use the headless primitives: see Headless components and Tailwind CSS.

The headless primitives from @mui/x-chat/headless render semantic HTML with zero built-in styles and data-* attributes for state—a natural fit for Tailwind:

import { Chat, Composer, Message, MessageList } from '@mui/x-chat/headless';

<Chat.Root adapter={adapter}>
  <Chat.Layout>
    <MessageList.Root renderItem={...} />
    <Composer.Root className="flex flex-col gap-1 border-t border-gray-200 p-3">
      <Composer.TextArea
        className="resize-none rounded-lg border border-gray-300 px-3 py-2 text-sm
                   focus:outline-none focus:ring-2 focus:ring-blue-500"
      />
      <Composer.Toolbar className="flex items-center justify-end gap-2">
        <Composer.SendButton
          className="rounded-lg bg-blue-600 px-3 py-1.5 text-sm text-white
                     hover:bg-blue-700 disabled:opacity-40"
        />
      </Composer.Toolbar>
    </Composer.Root>
  </Chat.Layout>
</Chat.Root>

Use data-* attributes for state-based styling without JavaScript:

{
  /* data-role="user" or data-role="assistant" */
}
<Message.Root className="flex gap-3 data-[role=user]:flex-row-reverse" />;

{
  /* The button gets the native disabled attribute while the input is empty; data-disabled reflects the composer's disabled prop */
}
<Composer.SendButton className="bg-blue-600 disabled:opacity-40" />;

These attributes are rendered by the headless primitives; the Material components consume the same state internally but expose it through classes instead.

Component Attribute Values
Message.Root data-role "user", "assistant"
Message.Root data-status "pending", "sending", "streaming", "sent", "read", "error", "cancelled"
Composer.SendButton data-disabled present when the composer is disabled via props
Composer.SendButton data-has-value present when the input is non-empty
Composer.Root data-is-streaming present / absent
ConversationList.Item data-selected present / absent

API

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