Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

Composer UI components

The default 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 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
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
AttachmentPreviewList AttachmentPreviewList The files, images and videos in the composer Below
LinkPreviewList LinkPreviewList A card for each link in the text Below
AttachmentSelector AttachmentSelector The button and menu to upload a file, create a poll, share a location or pick a command 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
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
AudioRecorder AudioRecorder The recorder, in place of the composer while 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
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 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 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 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 explains recording.

Hooks