Push to Talk

A hold-to-talk key for radios, voice notes and walkie-talkie chat. Live exactly while held, by pointer, keyboard or a global key, with a halo everyone reads as on air and a shake for a press too short to send.

  • Hold the button, or hold T.

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add push-to-talk

Usage#

usage.tsxTSX
import { PushToTalk } from "@/components/ui/push-to-talk"export function Example() {  return (    <PushToTalk      aria-label="Talk to the channel"      onTalkStart={() => recorder.start()}      onTalkEnd={() => recorder.send()}      onTalkCancel={() => recorder.discard()}    />  )}

Shapes#

circle (the default) is the icon alone, for a console where the key sits beside other controls; name it with aria-label and show that name in a Tooltip. pill says it in words and, while live, counts the time on air. Hold each one.

Sizes#

md (the default) is 40px, the hit target on its own; lg is 48px, for the main control of a console or a phone's bottom bar. The glyph steps up with it.

Variants#

The idle paint. neutral (the default) is the ink solid: a transmit key is a tool, not a brand moment. primary takes the brand, for a product whose main action is talking. Live is the same for both: the destructive fill and the halo.

Minimum duration#

A press shorter than minDuration (450ms by default) is a slip, not a message. It fires onTalkCancel instead of onTalkEnd, both with the duration, and the control shakes. Here the minimum is 600ms.

Tap it, then hold it.

Global shortcut#

shortcut makes a key transmit while held anywhere on the page, the way a radio console works. It stands down while focus is in a text field, while a modifier is held and while a dialog the control is not in is open. The key also lands in aria-keyshortcuts.

Hold V anywhere on the page

Labels and icons#

label and liveLabel set the words; timer={false} drops the count. icon and liveIcon swap the glyphs, which cross-fade on the live state.

Disabled#

disabled dims the control and turns its shortcut off. Disabling it while live ends the hold.

API reference#

PushToTalk

A <button> with aria-pressed and data-state="idle" | "live". Props: shape (circle · pill), size (md · lg), variant (neutral · primary), label, liveLabel, timer, icon, liveIcon, minDuration, shortcut, disabled, and the callbacks onTalkStart(), onTalkEnd(ms), onTalkCancel(ms) and onTalkingChange(talking). Every button prop is forwarded; className is merged last.

FAQ#

A Toggle stays on after you let go. Push to Talk is on only while held, so letting go is the send. Use a Toggle for mute; use Push to Talk for a transmit key.