# Input UI

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

The input UI is the component `MessageComposer` renders inside [`MessageComposerContext`](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/messagecomposercontext/): the whole visible composer. The default is `MessageComposerUI`, and you replace it with the `MessageComposerUI` override key. [Message composer UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-composer-ui/) explains its parts and what each one reads.

## Best practices

- Replace one part before you replace the whole layout. Each part has its own override key; see [Composer UI components](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/composer-ui-components/).
- Build a custom layout from the exported parts. They read the composer themselves, so suggestions, uploads and commands keep working.
- Scope `WithComponents` around one `MessageComposer` when only that composer should look different.
- Keep the `str-chat__message-composer*` class names if you want the default styling.

## Basic usage

Register your layout as `MessageComposerUI`. `MessageComposer` still provides the composer and the context:

```tsx
import {
  Channel,
  MessageComposer,
  MessageList,
  SendButton,
  TextareaComposer,
  useMessageComposerSubmitFn,
  WithComponents,
} from "stream-chat-react";

const CompactComposerUI = () => {
  const submit = useMessageComposerSubmitFn();

  return (
    <div className="compact-composer">
      <TextareaComposer />
      <SendButton sendMessage={submit} />
    </div>
  );
};

const overrides = { MessageComposerUI: CompactComposerUI };

export const ChannelWithCompactComposer = () => (
  <Channel channel={channel}>
    <MessageList />
    <WithComponents overrides={overrides}>
      <MessageComposer />
    </WithComponents>
  </Channel>
);
```

The send button and the Enter key both submit through `useMessageComposerSubmitFn()`: `MessageComposer.update()` while a message is being edited, `MessageComposer.send()` otherwise.

## UI customization

The default `MessageComposerUI` renders, in order:

1. `WithDragAndDropUpload` around everything, so files dropped on the composer are uploaded into it.
2. While a voice recording is in progress, `AudioRecorder` in place of all the rest.
3. `AttachmentSelector`. Inside a message, as when a message is edited where it sits, `SimpleAttachmentSelector` instead: a plain upload button.
4. The previews, only when there's something to preview:
   - `EditedMessagePreview` while a message is being edited, otherwise `QuotedMessagePreview`;
   - `VoiceRecordingPreviewSlot`;
   - `AttachmentPreviewList`;
   - `LinkPreviewList`;
   - the location to share. This preview has no override key.
5. The controls:
   - `CommandChip`, while a command is selected;
   - `TextareaComposer`;
   - `SendToChannelCheckbox`, in a thread;
   - `AdditionalMessageComposerActions`, which holds the `EmojiPicker` override;
   - `MessageComposerActions`: the send button, the cooldown timer, the record button or the stop button for an AI reply.

Every part except `WithDragAndDropUpload`, `MessageComposerActions` and the location preview is read from an override key, so a replacement registered with `WithComponents` shows in the default layout too.

A custom layout can keep the same structure. This one leaves out the edit preview, the also-send-to-channel checkbox and the emoji picker:

```tsx
import {
  AttachmentPreviewList,
  AttachmentSelector,
  AudioRecorder,
  LinkPreviewList,
  MessageComposer,
  MessageComposerActions,
  QuotedMessagePreview,
  TextareaComposer,
  useMessageComposerContext,
  VoiceRecordingPreviewSlot,
  WithComponents,
  WithDragAndDropUpload,
} from "stream-chat-react";

const CustomComposerUI = () => {
  const { recordingController } = useMessageComposerContext();

  return (
    <WithDragAndDropUpload
      className="str-chat__message-composer-container"
      component="div"
    >
      <div className="str-chat__message-composer">
        {recordingController.recordingState ? (
          <AudioRecorder />
        ) : (
          <>
            <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 />
                <MessageComposerActions />
              </div>
            </div>
          </>
        )}
      </div>
    </WithDragAndDropUpload>
  );
};

const overrides = { MessageComposerUI: CustomComposerUI };

export const ComposerWithCustomLayout = () => (
  <WithComponents overrides={overrides}>
    <MessageComposer audioRecordingEnabled />
  </WithComponents>
);
```

`EditedMessagePreview`, `SendToChannelCheckbox` and `StopAIGenerationButton` aren't exported, so a custom layout can't render their defaults. `MessageComposerActions` still renders the default stop button. When a command is selected, the default layout also adds the `str-chat__message-composer--command-active` class; see [Command-state behavior](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/composer-ui-components/#command-state-behavior).

The [Custom composer recipe](https://getstream.io/chat/docs/sdk/react/v15/recipes/composer/custom-composer/) builds a complete layout.

## Props

The input UI receives no props. It reads what it needs from:

- `useMessageComposerContext()`: the `MessageComposer` props, the textarea ref and the recorder;
- `useMessageComposerController()`: the composer and its stores;
- the [composer hooks](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/), such as `useMessageComposerSubmitFn()` and `useAttachmentManagerState()`.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/input-ui/](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/input-ui/).