KQ-758 · DRAFT/PARK
Draft Park
A composer with a parking rail beneath it. Park takes the field's draft and puts it aside: a ghost of the text drops out of the field on the exit ease while a chip with its first words lands on the rail from sixteen pixels on glide — a layout move, no bounce. Pressing the chip slides it back, the chip leaving upward on the exit ease as the text arrives in the field on glide with the caret at its end; a draft already in the field is parked in the same motion, so a restore is a swap and nothing is lost. The rail is measured, so its height glides to the chip rows, and drafts persist across runs: Send clears the field while the rail keeps every chip.
No parked drafts
No drafts · type, then park
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/draft-park
Props
- value / defaultValue
- string
- default ""
- Controlled or initial field text.
- onValueChange
- (value: string) => void
- default —
- Fires from every edit, a park and a restore.
- drafts / defaultDrafts
- ParkedDraft[]
- default []
- Controlled or initial parked drafts, { id, text }, newest last.
- onDraftsChange
- (drafts: ParkedDraft[]) => void
- default —
- Fires from a park, a restore and a discard with the whole rail.
- onPark
- (draft: ParkedDraft) => void
- default —
- Fires from the Park button, and from a restore that swapped the field's draft out, with the draft it made.
- onRestore
- (draft: ParkedDraft) => void
- default —
- Fires from a chip press with the draft it returned.
- onDiscard
- (draft: ParkedDraft) => void
- default —
- Fires from a chip's discard button.
- onSend
- (value: string) => void
- default —
- Fires from Enter or the Send button with the trimmed draft; the field clears.
- live
- boolean
- default false
- A run is in flight: Send is held, Park and the rail still work.
- placeholder
- string
- default "Ask anything"
- Placeholder while the field is empty.
- label
- string
- default —
- Names the field.
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue | string | "" | Controlled or initial field text. |
| onValueChange | (value: string) => void | — | Fires from every edit, a park and a restore. |
| drafts / defaultDrafts | ParkedDraft[] | [] | Controlled or initial parked drafts, { id, text }, newest last. |
| onDraftsChange | (drafts: ParkedDraft[]) => void | — | Fires from a park, a restore and a discard with the whole rail. |
| onPark | (draft: ParkedDraft) => void | — | Fires from the Park button, and from a restore that swapped the field's draft out, with the draft it made. |
| onRestore | (draft: ParkedDraft) => void | — | Fires from a chip press with the draft it returned. |
| onDiscard | (draft: ParkedDraft) => void | — | Fires from a chip's discard button. |
| onSend | (value: string) => void | — | Fires from Enter or the Send button with the trimmed draft; the field clears. |
| live | boolean | false | A run is in flight: Send is held, Park and the rail still work. |
| placeholder | string | "Ask anything" | Placeholder while the field is empty. |
| label | string | — | Names the field. |