Chat Composer
The Stream Manager's composer. The "To:" picker, the message field with its count, the ↵ key and send, local commands after "/", and one quiet line for the exceptions.
X read-only
Installation
$ pnpm dlx shadcn@latest add @videorc/chat-composerUsage
import { ChatComposer } from "@/components/blocks/stream-manager/chat-composer";
import type { ChatDestination } from "@/components/blocks/stream-manager/chat-platform";const destinations: ChatDestination[] = [
{ id: "yt", platform: "youtube", state: "connected", write: "ready" },
{ id: "tw", platform: "twitch", state: "connected", write: "ready" },
{ id: "x", platform: "x", state: "connected", write: "read-only" },
];
<ChatComposer
destinations={destinations}
onSend={(text, { destinationIds }) => send(text, destinationIds)}
pending={sending}
/>;A message goes to every destination whose write is ready. With more than one, the "To:" picker lets the streamer narrow a send; onSend then gets the picked destinationIds, and without a pick it gets none. The draft must fit the strictest destination it reaches: 200 characters, 140 with X.
The line under the field speaks only for the exceptions: a destination the send skips ("X read-only"), a failed send's reason with Retry, and "Sending…" while a send is on its way. A finished send says nothing: the message shows up in chat.
Examples
Local commands
Pass commands and the field completes them after "/": ↑ and ↓ move, Tab or ↵ completes. A command runs through onCommand and never posts to chat; "//" sends one literal slash. notice is the composer's answer, read politely: "Marker saved at 30:44 · Untitled marker". The demo above wires Videorc's /marker and /clip.
A failed send
failures names each destination a send didn't reach, with its reason; onRetry adds Retry. YouTube's chip names it in words: its mark may not shrink to a chip's 12 px.
X read-only
The window owns the draft
Pass value and onValueChange when something else fills the field, such as a row's ⋯ Reply that writes "@Maya Chen ", and inputRef for ⌘L to focus it.
Theming
| Token or attribute | Meaning |
|---|---|
border-t px-2 py-2 | The flush region under a hairline, never a card |
InputGroup | The field, its picker, count, key and send |
text-label | The count and the notes line |
Badge destructive | A failed destination |
data-slot | chat-composer, chat-composer-count, chat-composer-status |
Keyboard
| Key | Action |
|---|---|
| Enter | Sends, or runs a local command |
| ↑ ↓ | Move through the command completions |
| Tab | Completes the chosen command |
| Esc | Closes the completions |
Accessibility
The field is named "Message", or "Message or local command" with commands. The send button's name says where it sends: "Send message to all writable destinations", "Send message to Twitch", or why it can't. The picker is named "Send to: All". notice is a polite status, and an over-limit count carries the alert icon as well as its number.
API reference
Prop
Type
ChatComposerCommand
Prop
Type
ChatSendFailure
Prop
Type
chatDestinationNotes(destinations, sendPlatforms) and chatDraftMaxChars(platforms) are the rules the composer follows, for a status of your own.
Chat Toolbar
The Stream Manager chat's filter strip. Platform chips, Buddy's Questions, Mentions and a search field with its ⌘F key; below 640 px of Stream Manager the filters fold into one Filters menu.
Stream Stats Bar
The Stream Manager's stats bar. One 32 px row with the ON AIR clock, viewers and followers in the main slots and the rest after a hairline; monochrome numbers, details one hover away, and stats the streamer drags and picks.