KQ-856 · DRAFT/BADGE
Draft Badge
A channel list that remembers what you did not send. Leaving a channel with unsent text puts a badge on its row — a pencil and the draft's first words rising from four pixels on snap in place of the topic line, so the row never changes height — and opening it again drops the badge out on the exit ease while the same text arrives in the composer from eight pixels above on glide, caret at the end. The rows are tabs with a roving tabindex: arrows move, Home and End jump, Enter or Space opens; Enter in the composer sends and Shift+Enter breaks the line.
KQ-856 · DRAFT/BADGE
#dispatch open · 2 drafts · open a badged row
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/draft-badge
Props
- channels
- DraftChannel[]
- default —
- The rows: id, a name printed after a hash, and the topic shown while the channel holds no draft.
- drafts / defaultDrafts
- Record<string, string>
- default {}
- Controlled or initial draft text per channel id.
- onDraftsChange
- (drafts: Record<string, string>) => void
- default —
- Fires from every keystroke and from the clear after a send.
- active / defaultActive
- string
- default —
- Controlled or initial open channel id; defaults to the first channel.
- onActiveChange
- (id: string) => void
- default —
- Fires from a row press or the key that opened a channel.
- onSend
- (channelId: string, text: string) => void
- default —
- Fires from Enter or the Send button with the trimmed text of the open channel.
- placeholder
- string
- default "Message"
- Composer placeholder.
- label
- string
- default —
- Names the channel list for assistive technology; the composer is named after the open channel.
| Prop | Type | Default | Description |
|---|---|---|---|
| channels | DraftChannel[] | — | The rows: id, a name printed after a hash, and the topic shown while the channel holds no draft. |
| drafts / defaultDrafts | Record<string, string> | {} | Controlled or initial draft text per channel id. |
| onDraftsChange | (drafts: Record<string, string>) => void | — | Fires from every keystroke and from the clear after a send. |
| active / defaultActive | string | — | Controlled or initial open channel id; defaults to the first channel. |
| onActiveChange | (id: string) => void | — | Fires from a row press or the key that opened a channel. |
| onSend | (channelId: string, text: string) => void | — | Fires from Enter or the Send button with the trimmed text of the open channel. |
| placeholder | string | "Message" | Composer placeholder. |
| label | string | — | Names the channel list for assistive technology; the composer is named after the open channel. |