# Composer UI components

> **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 default [input UI](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/input-ui/) is built from the parts on this page. Each part reads the composer from `useMessageComposerController()`, so it works in a channel, in a thread and while editing. [Message composer UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-composer-ui/) explains what each part shows and which store it reads.

## Best practices

- Replace a part by registering it under its override key with `WithComponents`, so the default layout keeps the rest.
- Render the parts inside `MessageComposer`. Several of them, such as `TextareaComposer` and `MessageComposerActions`, read `MessageComposerContext` and throw outside it.
- Keep `TextareaComposer` in a custom layout, so mentions, commands and the Enter key keep working.
- The default layout passes a few parts what they need, such as `command` to `CommandChip` and `sendMessage` to `SendButton`. To set any other prop of a part, register a component that renders the part with it.

## Available building blocks

| Component                                      | Override key                       | What it renders                                                                                 | Props                                                                                                     |
| ---------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `TextareaComposer`                             | `TextareaComposer`                 | The text input and its suggestion list                                                          | [Below](#textareacomposer-props)                                                                          |
| `CommandChip`                                  | `CommandChip`                      | The selected command, with ✕ to clear it                                                        | `command`. Renders nothing without one                                                                    |
| `QuotedMessagePreview`                         | `QuotedMessagePreview`             | The message being replied to, with ✕ to remove it                                               | `getQuotedMessageAuthor`, `renderText`                                                                    |
| not exported                                   | `EditedMessagePreview`             | The message being edited, with ✕ to cancel the edit                                             | `message`, `onCancel`                                                                                     |
| `VoiceRecordingPreviewSlot`                    | `VoiceRecordingPreviewSlot`        | A voice recording waiting to be sent                                                            | [Below](#voicerecordingpreviewslot-props)                                                                 |
| `AttachmentPreviewList`                        | `AttachmentPreviewList`            | The files, images and videos in the composer                                                    | [Below](#attachmentpreviewlist-slots)                                                                     |
| `LinkPreviewList`                              | `LinkPreviewList`                  | A card for each link in the text                                                                | [Below](#linkpreviewlist-props)                                                                           |
| `AttachmentSelector`                           | `AttachmentSelector`               | The button and menu to upload a file, create a poll, share a location or pick a command         | [Attachment Selector](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/attachment-selector/) |
| `AdditionalMessageComposerActions`             | `AdditionalMessageComposerActions` | The area after the input. It renders the `EmojiPicker` override, except during a cooldown       | none                                                                                                      |
| `EmojiPicker`, from `stream-chat-react/emojis` | `EmojiPicker`                      | The emoji picker button and popover                                                             | [Emoji Picker](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/emoji-picker/)               |
| `MessageComposerActions`                       | none                               | One of: the cooldown timer, the record button, the stop button for an AI reply, the send button | none                                                                                                      |
| `SendButton`                                   | `SendButton`                       | The send button. Disabled until the composer has something to send                              | `sendMessage`, and any `<button>` prop                                                                    |
| `CooldownTimer`                                | `CooldownTimer`                    | The seconds left of a slow-mode cooldown                                                        | none                                                                                                      |
| `StartRecordingAudioButton`                    | `StartRecordingAudioButton`        | The record button                                                                               | [Audio Recorder](https://getstream.io/chat/docs/sdk/react/v15/component-reference/voice-recording/audio-recorder/)            |
| `AudioRecorder`                                | `AudioRecorder`                    | The recorder, in place of the composer while recording                                          | [Audio Recorder](https://getstream.io/chat/docs/sdk/react/v15/component-reference/voice-recording/audio-recorder/)            |
| not exported                                   | `StopAIGenerationButton`           | The button that stops an AI reply. `null` turns it off                                          | any `<button>` prop                                                                                       |
| not exported                                   | `SendToChannelCheckbox`            | The "Also send in channel" checkbox, in a thread and not while editing                          | none                                                                                                      |
| `WithDragAndDropUpload`                        | none                               | A drop zone that uploads files into the composers inside it                                     | [WithDragAndDropUpload](https://getstream.io/chat/docs/sdk/react/v15/component-reference/utilities/withdraganddropupload/)    |
| `FileDragAndDropContent`                       | none                               | The "Drag your files here" overlay of `WithDragAndDropUpload`                                   | `isDragRejected`                                                                                          |

`WithComponents` accepts a `FileDragAndDropContent` key, but `WithDragAndDropUpload` doesn't read it and always renders the default overlay.

`MessageComposerActions` picks its control in this order: the cooldown timer during a cooldown; the record button when the composer is empty, nothing is being edited, no command is active and recording is turned on; the stop button while an AI reply is being generated; the send button otherwise. While editing or with a command, the default send button shows a checkmark.

## Command-state behavior

When the user selects a command, such as `/giphy`, the default layout:

- adds the `str-chat__message-composer--command-active` class to the composer;
- shows `CommandChip` before the input;
- hides `AttachmentSelector` and `AdditionalMessageComposerActions` with a CSS transition, and takes them out of the tab order;
- leaves the record button out of `MessageComposerActions`;
- changes the placeholder of the input to the command's arguments, or to "Search GIFs" for `/giphy`.

Escape, or Backspace in an empty input, clears the command. A custom layout gets the chip and the placeholder from the parts, and decides the rest itself. [Commands and Giphy](https://getstream.io/chat/docs/sdk/react/v15/features/rich-content/commands-and-giphy/) explains commands.

## `TextareaComposer` props

`TextareaComposer` takes every `<textarea>` prop except `defaultValue`, `disabled`, `style` and `value`, and these:

| Prop                             | Type                                                           | Default                                            | Description                                                                |
| -------------------------------- | -------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------- |
| `closeSuggestionsOnClickOutside` | `boolean`                                                      | `true`                                             | Closes the suggestion list when the user clicks outside it.                |
| `containerClassName`             | `string`                                                       | none                                               | Class name added to the `div` around the textarea and the suggestion list. |
| `listClassName`                  | `string`                                                       | none                                               | Class name added to the suggestion list.                                   |
| `maxRows`                        | `number`                                                       | the `MessageComposer` prop, or `10`                | The most rows the input grows to.                                          |
| `minRows`                        | `number`                                                       | the `MessageComposer` prop                         | The fewest rows the input shows. Without it, an empty input is one row.    |
| `shouldSubmit`                   | `(event: React.KeyboardEvent<HTMLTextAreaElement>) => boolean` | the `MessageComposer` prop, or Enter without Shift | Decides which key press submits.                                           |

Some `<textarea>` props behave in a particular way:

- `placeholder` replaces "Send a message". A command's placeholder and the cooldown's "Slow mode, wait 5s..." still take its place.
- `className` is added to the default class names.
- `onChange`, `onKeyDown` and `onScroll` replace the default handling. With your own `onChange`, typing no longer reaches the composer. With your own `onKeyDown`, Enter no longer submits and the arrow keys no longer move through suggestions.
- `onSelect` runs before the default handling, which keeps the composer's cursor position.
- `onPaste` is ignored. The input always uses the paste handler from `MessageComposerContext`.

The input is disabled while the composer's `text.enabled` setting is `false`, and during a slow-mode cooldown.

## `LinkPreviewList` props

| Prop               | Type     | Default | Description                                 |
| ------------------ | -------- | ------- | ------------------------------------------- |
| `displayLinkCount` | `number` | `1`     | How many link previews show, in text order. |

The list shows the previews that are loading or loaded. To show more than one, register a `LinkPreviewList` that renders the default with `displayLinkCount`. [Link previews](https://getstream.io/chat/docs/sdk/react/v15/features/rich-content/link-previews/) explains them.

## `AttachmentPreviewList` slots

`AttachmentPreviewList` renders the files, images and videos in the composer, each with its upload progress, and opens images and videos in a gallery. It leaves out:

- link previews, which `LinkPreviewList` renders;
- voice recordings, which `VoiceRecordingPreviewSlot` renders;
- the location to share, which the default layout renders separately.

Each slot replaces the preview of one kind of attachment:

| Prop                           | Type                                                                                      | Default                        | Previews                      |
| ------------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------ | ----------------------------- |
| `AudioAttachmentPreview`       | `ComponentType<AudioAttachmentPreviewProps> \| ComponentType<FileAttachmentPreviewProps>` | the file preview               | Audio files                   |
| `FileAttachmentPreview`        | `ComponentType<FileAttachmentPreviewProps>`                                               | the file preview               | Other files                   |
| `ImageAttachmentPreview`       | `ComponentType<ImageAttachmentPreviewProps>`                                              | the media preview              | Images                        |
| `UnsupportedAttachmentPreview` | `ComponentType<UnsupportedAttachmentPreviewProps>`                                        | `UnsupportedAttachmentPreview` | Attachments of any other type |
| `VideoAttachmentPreview`       | `ComponentType<MediaAttachmentPreviewProps>`                                              | the media preview              | Videos                        |

Each preview gets the `attachment`, `handleRetry` to upload it again and `removeAttachments` to remove it. Image and video previews also get `openPreview`, which opens the gallery at that attachment. The default file and media previews aren't exported. `AudioAttachmentPreviewProps` and `MediaAttachmentPreviewProps` aren't exported either; read them from `AttachmentPreviewListProps`, as in `AttachmentPreviewListProps["VideoAttachmentPreview"]`.

To set the slots, register an `AttachmentPreviewList` that renders the default with them. The [Attachment previews recipe](https://getstream.io/chat/docs/sdk/react/v15/recipes/composer/attachment-previews/) does this.

## Upload progress and size indicators

The previews show an upload with these components:

| Component                         | Props                                         | What it renders                                                                                                                                                                                  |
| --------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `UploadProgressIndicator`         | `uploadProgress`, `uploadConfirmationPending` | The `ProgressIndicator` override, a ring showing the percent sent. The `LoadingIndicator` override when the progress is unknown, or when every byte is sent and the server hasn't confirmed yet. |
| `AttachmentUploadedSizeIndicator` | `attachment`, `uploadProgress`                | While uploading, the `UploadedSizeIndicator` override with the bytes sent and the total. Once uploaded, the `FileSizeIndicator` override with the file's size.                                   |
| `UploadedSizeIndicator`           | `uploadedBytes`, `fullBytes`                  | "sent / total", each formatted by the `FileSizeIndicator` override.                                                                                                                              |
| `FileSizeIndicator`               | `fileSize`, `maximumFractionDigits`           | A byte size, such as "2.4 MB".                                                                                                                                                                   |

By default:

- file previews show the progress ring and the size while uploading, and the size once uploaded;
- voice recording previews show the progress ring while uploading, and the size until the recording's duration is known;
- image and video previews show the progress ring over the thumbnail, and no size.

To change these without replacing the previews, register `ProgressIndicator`, `LoadingIndicator`, `UploadedSizeIndicator` or `FileSizeIndicator` with `WithComponents`. `ProgressIndicator` gets `percent`, from 0 to 100.

## `VoiceRecordingPreviewSlot` props

| Prop                    | Type                                        | Default                    | Description                                                           |
| ----------------------- | ------------------------------------------- | -------------------------- | --------------------------------------------------------------------- |
| `VoiceRecordingPreview` | `ComponentType<VoiceRecordingPreviewProps>` | the voice recording player | The preview of the recording, which the user can play before sending. |

The slot shows the first voice recording in the composer, above the attachment list. It gets the same props as the attachment previews: `attachment`, `handleRetry` and `removeAttachments`. [Voice recordings and audio playback](https://getstream.io/chat/docs/sdk/react/v15/features/rich-content/voice-recordings-and-audio-playback/) explains recording.

## Hooks

- [`useAttachmentManagerState`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#useattachmentmanagerstate): the attachments and how many more fit.
- [`useAttachmentsForPreview`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#useattachmentsforpreview): the attachments, the poll and the location to preview.
- [`useMessageComposerHasSendableData`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#usemessagecomposerhassendabledata): whether the send button is enabled.
- [`useMessageComposerCommands`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#usemessagecomposercommands): the channel's commands and whether each one can be used.

---

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