import {
AttachmentPreviewList,
LinkPreviewList,
QuotedMessagePreview,
SimpleAttachmentSelector,
useComponentContext,
useMessageInputContext,
} from "stream-chat-react";
const SendButtonWithCooldown = () => {
const { handleSubmit, cooldownRemaining, setCooldownRemaining } =
useMessageInputContext();
return cooldownRemaining ? (
<CooldownTimer
cooldownInterval={cooldownRemaining}
setCooldownRemaining={setCooldownRemaining}
/>
) : (
<SendButton sendMessage={handleSubmit} />
);
};
const CustomMessageInput = () => (
<div className="message-input">
<div className={"left-container"}>
<SimpleAttachmentSelector />
</div>
<div className={"central-container"}>
<QuotedMessagePreview />
<LinkPreviewList />
<AttachmentPreviewList />
<TextareaComposer />
</div>
<div className={"right-container"}>
<SendButtonWithCooldown />
</div>
</div>
);Message Input UI
Message input is used for composing and editing messages. It’s a primary interaction point in chat, so it’s worth getting right.
Message input is more than a text box + “send” button. It includes:
- Updating the typing status
- Uploading and previewing attachments
- Displaying link previews
- Auto-completing mentions, commands, emoji...
Best Practices
- Compose input from pre-built components to preserve core behaviors.
- Keep
TextareaComposercentral for autocomplete and commands. - Use
MessageInputContextinstead of passing handlers manually. - Avoid rendering custom inputs outside
Channel/MessageInput. - Test attachments, previews, and typing updates together.
You can compose your Input UI component from pre-built components:
Don’t render your custom input directly. Instead pass it as a prop to
either Channel or
MessageInput component. That way,
your input is wrapped with the necessary context providers, especially
the MessageInputContext.
import {
Chat,
Channel,
ChannelHeader,
ChannelList,
MessageList,
Thread,
Window,
MessageInput,
} from "stream-chat-react";
import { CustomMessageInput } from "./CustomMessageInput";
export const App = () => (
<Chat client={chatClient}>
<ChannelList filters={filters} sort={sort} options={options} />
<Channel>
<Window>
<ChannelHeader />
<MessageList />
<MessageInput Input={CustomMessageInput} />
</Window>
<Thread />
</Channel>
</Chat>
);