SpeechInput
Dictate a message: pick a microphone, speak, and insert what was heard.
SourcePackage @kerf-js/veneer
Preview
tsx
import { Prompt, SpeechInput, Stack} from '@kerf-js/veneer'import type { PromptControl, SpeechInputProps} from '@kerf-js/veneer'export function Dictate() { let prompt: PromptControl | undefined return ( <Stack gap="group"> <SpeechInput mics={MICS} engine={fakeEngine} onInsert={(text) => prompt?.insert(text)} /> <Prompt tools={[]} control={(c) => (prompt = c)} placeholder="Your dictation lands here" /> </Stack> )}const MICS = [ { value: 'mbp', label: 'MacBook Pro Microphone' }, { value: 'pods', label: 'AirPods Pro' },]const WORDS = [ 'Roll back', 'Roll back mobile-bff', 'Roll back mobile-bff in ap-south',]const fakeEngine = ( on: Parameters< NonNullable<SpeechInputProps['engine']> >[0],) => { let timer: ReturnType<typeof setInterval> return { start() { let i = 0 on.onState('listening') timer = setInterval(() => { if (i < WORDS.length) { on.onTranscript( i ? WORDS[i - 1]! : '', WORDS[i]!.slice(i ? WORDS[i - 1]!.length : 0), ) on.onLevel(0.3 + (i % 2) * 0.4) i++ } else { on.onTranscript(WORDS[WORDS.length - 1]!, '') clearInterval(timer) on.onState('idle') } }, 800) }, stop() { clearInterval(timer) on.onState('idle') }, }}Installation
npm install @kerf-js/veneerUsage
tsx
import { SpeechInput } from '@kerf-js/veneer'With words waiting
Grey words might still change.
tsx
import { SpeechInput } from '@kerf-js/veneer'import type { SpeechInputProps } from '@kerf-js/veneer'export function Transcript() { return ( <SpeechInput mics={MICS} engine={fakeEngine} initial={{ final: 'Show me the failing', interim: 'check', }} /> )}const MICS = [ { value: 'mbp', label: 'MacBook Pro Microphone' }, { value: 'pods', label: 'AirPods Pro' },]const WORDS = [ 'Roll back', 'Roll back mobile-bff', 'Roll back mobile-bff in ap-south',]const fakeEngine = ( on: Parameters< NonNullable<SpeechInputProps['engine']> >[0],) => { let timer: ReturnType<typeof setInterval> return { start() { let i = 0 on.onState('listening') timer = setInterval(() => { if (i < WORDS.length) { on.onTranscript( i ? WORDS[i - 1]! : '', WORDS[i]!.slice(i ? WORDS[i - 1]!.length : 0), ) on.onLevel(0.3 + (i % 2) * 0.4) i++ } else { on.onTranscript(WORDS[WORDS.length - 1]!, '') clearInterval(timer) on.onState('idle') } }, 800) }, stop() { clearInterval(timer) on.onState('idle') }, }}Accessibility
- Nothing is sent until Insert. A blocked microphone shows how to fix it instead of a dead button.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
mics | { value: string; label: string; }[] | — | The microphones on offer. |
engine | ((on: DictationEvents) => DictationEngine) | — | Replaces the browser's speech recognition. |
initial | { state?: DictationState | undefined; final?: string | undefined; interi… | — | The state and words to start from. |
| Event | Type | Default | Description |
|---|---|---|---|
onInsert | ((text: string) => void) | — | Gets the transcript, usually for the Prompt's insert(). |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="speech"] [data-part="mic"]
miclevelstripwavetimetranscriptinterim
RelatedPrompt