KQ-1492 · TALK/PILL
Talk Pill
A voice input pill for a composer: pressing it grows the capsule leftward over the row on springs.snap into a recording pill with a breathing dot, a timer, a scrolling waveform tape and a fuse toward the longest take. Sliding left squeezes it under the finger 1:1 — the tape crowds and flattens and the pill blends toward danger until a detent at the cancel line — and a release there snaps it shut to a circle that pops away, while a shorter one springs back out with the throw's velocity on springs.snap; letting go of a hold sends the take with a small lift. It is a toggle button: Space or Enter starts and sends, Escape cancels, and a quick tap starts hands-free recording.
- Can you leave the gate code for Thursday?
hold to talk · space from the keyboard
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/talk-pill
Props
- onSend
- (take: { duration: number; levels: number[] }) => void
- default —
- A take was sent — by letting go of a hold, a second tap, Space or Enter, or the clock running out — with its length in ms and 32 levels.
- onCancel
- () => void
- default —
- A take was thrown away: squeezed past `cancel`, or Escape.
- onRecordingChange
- (recording: boolean) => void
- default —
- Recording started (true) or ended (false).
- bars
- number
- default 24
- How many bars the waveform tape shows.
- duration
- number
- default 30
- The longest take, in seconds; the fuse fills toward it and the take sends itself there.
- cancel
- number
- default 96
- How far left the pill must be squeezed to cancel, in px.
- level
- number
- default —
- The live input level, 0 to 1. Without it the tape shows a seeded, simulated voice.
- label
- string
- default "Hold to talk"
- The idle pill's text and the button's accessible name.
- hint
- string
- default "Slide to cancel"
- The slide hint while recording.
- releaseLabel
- string
- default "Release to cancel"
- What the hint becomes once a release would cancel.
- holdThreshold
- number
- default 250
- A press shorter than this, in ms, starts hands-free recording instead of a hold.
- color
- string
- default "var(--accent-bright)"
- The tape's colour.
- size
- "sm" | "md" | "lg"
- default "md"
- 36, 44 or 52px tall.
- seed
- number
- default 3
- Seeds the simulated voice.
- sound
- boolean
- default false
- A click as it starts and sends, a detent at the cancel line and a swish on cancel; only in answer to the visitor.
- disabled
- boolean
- default false
- Disables the pill; a take in progress is thrown away.
- className
- string
- default —
- Classes for the row.
- children
- React.ReactNode
- default —
- The rest of the row — a text field — which the recording pill covers (it is inert while recording).
| Prop | Type | Default | Description |
|---|---|---|---|
| onSend | (take: { duration: number; levels: number[] }) => void | — | A take was sent — by letting go of a hold, a second tap, Space or Enter, or the clock running out — with its length in ms and 32 levels. |
| onCancel | () => void | — | A take was thrown away: squeezed past `cancel`, or Escape. |
| onRecordingChange | (recording: boolean) => void | — | Recording started (true) or ended (false). |
| bars | number | 24 | How many bars the waveform tape shows. |
| duration | number | 30 | The longest take, in seconds; the fuse fills toward it and the take sends itself there. |
| cancel | number | 96 | How far left the pill must be squeezed to cancel, in px. |
| level | number | — | The live input level, 0 to 1. Without it the tape shows a seeded, simulated voice. |
| label | string | "Hold to talk" | The idle pill's text and the button's accessible name. |
| hint | string | "Slide to cancel" | The slide hint while recording. |
| releaseLabel | string | "Release to cancel" | What the hint becomes once a release would cancel. |
| holdThreshold | number | 250 | A press shorter than this, in ms, starts hands-free recording instead of a hold. |
| color | string | "var(--accent-bright)" | The tape's colour. |
| size | "sm" | "md" | "lg" | "md" | 36, 44 or 52px tall. |
| seed | number | 3 | Seeds the simulated voice. |
| sound | boolean | false | A click as it starts and sends, a detent at the cancel line and a swish on cancel; only in answer to the visitor. |
| disabled | boolean | false | Disables the pill; a take in progress is thrown away. |
| className | string | — | Classes for the row. |
| children | React.ReactNode | — | The rest of the row — a text field — which the recording pill covers (it is inert while recording). |