Skip to content
+

Chat - Composer

Compose and send chat messages with an auto-resizing text area, keyboard shortcuts, and attachment support.

Overview

The composer is the input region at the bottom of the chat surface. ChatComposer provides Material UI styling: border, padding, and theme tokens are applied automatically. The demos on this page render only the composer plus the provider context it depends on.

Interactive playground

Try the ChatComposer props live: toggle variant, attachments, helper text, and placeholder:

ChatComposer
Form surface for the prompt — attachment list, textarea, toolbar.

Press Enter to send, Shift+Enter for a new line.

props
variantenum · 2
disabled
palette.action.disabledBackground.
features.attachments
attachments
Show the attach button + preview list.
acceptedMimeTypesstring
Comma-separated MIME list.
maxFileCount
0 disables the limit.
maxFileSizeunlimited
0 disables the limit.
composition (children)
ChatComposerTextArea.placeholderstring
render ChatComposerHelperText
default variant only.

Import

import {
  ChatComposer,
  ChatComposerLabel,
  ChatComposerTextArea,
  ChatComposerSendButton,
  ChatComposerAttachButton,
  ChatComposerAttachmentList,
  ChatComposerToolbar,
  ChatComposerHelperText,
} from '@mui/x-chat';

Component anatomy

Inside ChatBox, the composer renders the following structure:

ChatComposer                  ← <form> element, border-top divider
  ChatComposerLabel           ← optional <label> for accessibility
  ChatComposerTextArea        ← auto-resizing textarea
  ChatComposerToolbar         ← button row
    ChatComposerAttachButton  ← file attach trigger
    ChatComposerSendButton    ← submit button (disabled when the draft is empty or while streaming)
  ChatComposerHelperText      ← disclaimer or character count

Variants

ChatComposer accepts variant="default" (a bordered box with the textarea above a ChatComposerToolbar button row) or variant="compact" (a single-row layout where ChatComposerAttachButton and ChatComposerSendButton are placed directly as children, with no toolbar).

The variant can also come from the surrounding chat context; an explicit prop wins over the context value.

variant="default"
variant="compact"

Text area

ChatComposerTextArea is an auto-resizing <textarea> that grows with content. It submits on Enter and inserts a newline on Shift+Enter.

Use maxRows to cap the auto-grow: the textarea starts at one row and grows up to maxRows lines, then scrolls.

Customizing the placeholder

Customize the placeholder directly on ChatComposerTextArea:

This standalone example customizes the textarea placeholder directly.

IME composition

The composer handles IME (Input Method Editor) composition for CJK languages. While the user is composing characters (for example, selecting Kanji), pressing Enter confirms the character selection instead of submitting the message. Submission is blocked until composition ends.

Send button

ChatComposerSendButton disables automatically when:

  • The text area is empty and there are no queued attachments.
  • A response is currently streaming.
  • The composer is explicitly disabled.

Attach button

The attach button opens the browser file picker. Selected files are queued as draft attachments and previewed in the composer area.

Omit ChatComposerAttachButton from the toolbar when attachments are not part of the surface:

This toolbar omits ChatComposerAttachButton, leaving only the send action.

Files that exceed the configured limits (maxFileCount, maxFileSize, acceptedMimeTypes) are not queued and there is no built-in rejection UI — handle the onAttachmentReject callback to surface feedback.

See Attachments for details on accepted MIME types, file size limits, and the upload lifecycle.

Helper text

A helper text line appears below the composer. Use it for legal disclaimers, character counts, or contextual hints.

Files are uploaded after you send.

Controlled composer value

Control the composer value externally through ChatProvider state. The demo below mirrors the current composer value above the standalone composer:

Composer value: (empty)

The current draft value is controlled outside the composer.

Accessing composer state with a hook

For deeper control, the useChatComposer() hook provides direct access to the composer state:

Current value: (empty)

Attachments: 0

Submitting: No

Type, attach a file, or send to watch the hook state update.

Press Enter to start editing

The hook returns:

Property Type Description
value string Current text value
setValue (value: string) => void Update the text value
attachments ChatDraftAttachment[] Queued file attachments
addAttachment (file: File) => void Add a file to the draft
removeAttachment (localId: string) => void Remove a queued file
clear () => void Reset value and attachments
submit () => Promise<void> Submit the current draft
isSubmitting boolean Whether a send is in progress

Disabling the composer

Pass disabled to ChatComposer to prevent all interaction. When disabled, the text area is read-only and the send button is inert.

Disabled state comes from ChatComposer and makes the entire draft surface inert.

Accessibility

The text area resolves its accessible name through a fallback chain: an explicit aria-label wins; passing aria-labelledby suppresses the default; otherwise the locale text composerInputAriaLabel ("Message") is applied automatically.

ChatComposerLabel renders a visible <label>. Wire it to the text area with htmlFor (plus aria-labelledby/id) to avoid a duplicate accessible name. With no children it falls back to the same composerInputAriaLabel text, keeping the visible and announced names consistent. Use it when the design calls for a visible label; otherwise the automatic aria-label is enough.

The send and attach buttons get their accessible names from composerSendButtonLabel and composerAttachButtonLabel (see the Localization table below).

For the full keyboard navigation and accessibility model, see the message list reference.

Localization

The composer uses these locale text keys (customizable via localeText on ChatBox or ChatRoot):

Key Default Used by
composerInputPlaceholder "Type a message" TextArea placeholder
composerInputAriaLabel "Message" TextArea aria-label, Label fallback
composerSendButtonLabel "Send message" SendButton aria-label
composerAttachButtonLabel "Add attachment" AttachButton aria-label

API

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