This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13) .

Input UI

The Input UI component consumes MessageInputContext and renders the visible composer. The default implementation is MessageInputFlat.

Best Practices

  • Start from the exported building blocks before replacing the whole composer.
  • Pass a custom input through MessageInput Input={...} for one-off layouts.
  • Use WithComponents for shared subcomponent overrides.
  • Keep the preview stack and textarea together so autocomplete, uploads, and recording state remain coherent.
  • If you want the default slash-command UX, keep CommandChip next to TextareaComposer and hide attachment or extra-action controls while a command is selected.
  • Reuse the default str-chat__message-composer* classes if you want to keep the built-in styling.

Basic Usage

Use MessageInput Input={...} to replace the whole composer UI for a specific instance.

import {
  Channel,
  ChannelHeader,
  MessageInput,
  MessageList,
  Thread,
  Window,
} from "stream-chat-react";

const CustomInput = () => <div className="custom-input-shell">...</div>;

const App = () => (
  <Channel>
    <Window>
      <ChannelHeader />
      <MessageList />
      <MessageInput Input={CustomInput} />
    </Window>
    <Thread />
  </Channel>
);

UI Customization

MessageInputFlat is a good reference for a custom composer. In v14 the default structure is:

  • AttachmentSelector
  • preview stack:
    • EditedMessagePreview or QuotedMessagePreview
    • VoiceRecordingPreviewSlot
    • AttachmentPreviewList
    • LinkPreviewList
  • text and action controls:
    • CommandChip
    • TextareaComposer
    • SendToChannelCheckbox
    • AdditionalMessageComposerActions
    • MessageComposerActions

A simplified custom input can keep the same composition model:

import {
  AttachmentPreviewList,
  AttachmentSelector,
  LinkPreviewList,
  MessageComposerActions,
  MessageInput,
  QuotedMessagePreview,
  SendToChannelCheckbox,
  TextareaComposer,
  VoiceRecordingPreviewSlot,
  WithDragAndDropUpload,
} from "stream-chat-react";

const CustomInput = () => (
  <WithDragAndDropUpload
    className="str-chat__message-composer-container"
    component="div"
  >
    <div className="str-chat__message-composer">
      <AttachmentSelector />
      <div className="str-chat__message-composer-compose-area">
        <div className="str-chat__message-composer-previews">
          <QuotedMessagePreview />
          <VoiceRecordingPreviewSlot />
          <AttachmentPreviewList />
          <LinkPreviewList />
        </div>
        <div className="str-chat__message-composer-controls">
          <TextareaComposer />
          <SendToChannelCheckbox />
          <MessageComposerActions />
        </div>
      </div>
    </div>
  </WithDragAndDropUpload>
);

const Composer = () => <MessageInput Input={CustomInput} />;

When a slash command is selected, the default MessageInputFlat adds str-chat__message-composer--command-active, keeps the selected command visible through CommandChip, and collapses both AttachmentSelector and AdditionalMessageComposerActions. Mirror that behavior in your own layout only if you want parity with the default composer.

For a shared override across the app, register the input UI with WithComponents:

import { Channel, MessageInput, WithComponents } from "stream-chat-react";

const CustomInput = () => <div className="custom-input-shell">...</div>;

const App = () => (
  <WithComponents overrides={{ Input: CustomInput }}>
    <Channel>
      <MessageInput />
    </Channel>
  </WithComponents>
);

Props

PropDescriptionType
noneThe Input UI component itself does not receive required props. It should read the composer state it needs from useMessageInputContext(), useMessageComposer(), and the exported message-input hooks.-