Skip to content
Kura UI

Voice Dictation

experimental

Mic button that expands into a live waveform pill with a timer and live transcript; speech-to-text with recording fallback, toggle or hold-to-talk.

@kura-ui/react/voice-dictationCopy page for agents.mdregistry.json

Toggle with live transcript

minimal

Toggle or hold, hotkey and collected notes

Switch modes, use ⌘⇧D, and watch final transcripts collect below.

full
ToggleControl Shift D

Status: idle

  • Dictated notes appear here.

Dictating into a composer

Interim words preview in the placeholder; the final transcript is appended to the composer value.

composition

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/voice-dictation.json

Copies the source into components/kura/voice-dictation with its dependencies (kura-theme, audio-waveform, kura-keys, kura-motion, shimmer-text, spinner, tooltip, use-audio-analyser, use-hotkey, use-media-recorder, use-reduced-motion, use-speech-recognition, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • Let users dictate a prompt instead of typing — standalone or in a composer toolbar.
  • Push-to-talk input (mode="hold") for voice notes or quick commands.
  • Browsers without the Web Speech API: record audio and transcribe on your server via `transcribe`.

Reach for something else when

  • A full-duplex conversation with a voice agent (barge-in, spoken replies) — use agent-orb with your realtime session.
  • Only visualising audio you already have — use audio-waveform.
  • Typing prompts — use composer.

Props

PropTypeDefaultDescription
onTranscript(text: string) => void—Called once per dictation with the final trimmed text. Not called when cancelled (× or Escape) or when nothing was heard.
onInterim(text: string) => void—Live text (final + interim) while listening, e.g. to preview in a placeholder.
onStatusChange(status: VoiceDictationStatus) => void—idle | requesting | listening | processing | denied | unsupported | error.
mode"toggle" | "hold""toggle"toggle = click to start/stop; hold = dictate while the pointer, Space/Enter or the hotkey is held.
hotkeyreadonly KeyName[] | null["mod", "shift", "d"]Global shortcut (works while typing). null disables it.
langstring—BCP-47 language for recognition, e.g. "en-US". Defaults to the page language.
transcribe(audio: Blob) => Promise<string>—Fallback transcription when the Web Speech API is missing (Firefox): receives the recording; status is “processing” until it resolves.
simulateboolean | string—Demo mode: fake permission, simulated waveform and a scripted transcript (a string is typed out word by word). For docs and tests.
showTranscriptbooleantrueShow the live transcript card under the control. Turn off inside a composer.
transcriptPlaceholderstring"Listening…"Text in the transcript card before words arrive.
disabledbooleanfalseDisable the control.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. VoiceDictationRoot column. data-status (see onStatusChange) and data-mode.data-slot="voice-dictation"
  2. VoiceDictationControlThe mic button; while live it grows (layout spring) into a signal-tinted pill with waveform, timer and cancel.data-slot="voice-dictation-control"
  3. VoiceDictationButtonMic / stop / mic-off button with aria-pressed and a tooltip showing the hotkey.data-slot="voice-dictation-button"
  4. VoiceDictationCancel× button that discards the dictation.data-slot="voice-dictation-cancel"
  5. VoiceDictationTranscriptLive transcript: final words in ink, interim words subtle, a signal caret while listening.data-slot="voice-dictation-transcript"
  6. VoiceDictationMessageRecovery text for denied / unsupported / error.data-slot="voice-dictation-message"

Accessibility

  • The button is labelled “Dictate” (or “Hold to dictate”) with aria-pressed reflecting listening; the stop/mic icon swap is visual only.
  • A visually hidden role=status announces state changes once (“Listening”, “Transcribing”, “Microphone access is blocked”) — never per word.
  • Denied and unsupported states keep a visible text explanation and the button stays reachable to retry.
  • The waveform is decorative (aria-hidden); the timer is plain text with tabular numbers.
  • Reduced motion: The pill appears without the layout spring, icon swaps fade without scale or blur, the waveform becomes a slow level meter and the caret stops blinking.
KeysAction
Enter / SpaceToggle dictation (hold them in hold mode)
Mod+Shift+DGlobal toggle / hold (configurable via hotkey)
EscapeCancel and discard while listening

Notes for agents

  • In docs, demos and tests pass `simulate` — real recognition needs a user gesture, mic permission and (for Chrome) a network connection.
  • Feed a Composer by controlling its value: onTranscript={(t) => setValue((v) => (v ? v + ' ' + t : t))}; pass showTranscript={false}.
  • Provide `transcribe` for Firefox/other browsers without SpeechRecognition; without it those browsers record but emit nothing.
  • Only one mounted instance should own a given hotkey; pass hotkey={null} on the others.
  • The listening pill uses the jade signal — avoid another accent-filled element in the same view while dictating.