'use client';
import { useEffect, useState } from 'react';
import { Button, LiveTranscript } from '@brand-studio/ui';
const phrases = ['Order two bags of the Huila', 'for North Street Café,', 'ground for filter,', 'and deliver them on Friday.'];
export default function LiveTranscriptDemo() {
const [step, setStep] = useState(-1);
const playing = step >= 0 && step < phrases.length * 4;
useEffect(() => {
if (!playing) return;
const timer = setTimeout(() => setStep(value => value + 1), 320);
return () => clearTimeout(timer);
}, [playing, step]);
// Each phrase shows as a growing guess for three ticks, then settles.
const phrase = Math.floor(step / 4), tick = step % 4;
const done = phrases.slice(0, playing ? phrase : phrases.length).join(' ');
const words = playing ? phrases[phrase].split(' ') : [];
const interim = playing && tick < 3 ? words.slice(0, Math.ceil(words.length * (tick + 1) / 3)).join(' ') : '';
const text = playing && tick === 3 ? [done, phrases[phrase]].filter(Boolean).join(' ') : step < 0 ? '' : done;
return (
<div style={{ width: '100%', maxWidth: 560, display: 'grid', gap: 20, justifyItems: 'start' }}>
<LiveTranscript text={text} interim={interim} listening={playing} />
<Button tone="secondary" onClick={() => setStep(0)} disabled={playing}>{step < 0 ? 'Play dictation' : 'Play again'}</Button>
</div>
);
}Installation
pnpm add @brand-studio/uinpm install @brand-studio/uiyarn add @brand-studio/uibun add @brand-studio/uiInstall the peer dependencies
npm install react react-domImport the stylesheet once
import '@brand-studio/ui/styles.css';Wrap your app in a brand theme
import { BrandTheme, LiveTranscript } from '@brand-studio/ui'; import brand from './brand.json'; <BrandTheme palette={brand.tokens} mode="system"> {/* your app */} </BrandTheme>
Usage
import { LiveTranscript } from '@brand-studio/ui';<LiveTranscript text={finalText} interim={guess} listening={listening} />Pass the settled words as text and speech recognition's current guess as interim. New settled words sharpen into full ink as they land. The guess stays faded after them, and a caret blinks while listening.
Accessibility
- Screen readers hear each newly settled phrase once and never the guesses.
- With reduced motion new words appear at once and the caret stays still.
API Reference
| Prop | Type | Default |
|---|---|---|
text | string | – |
interim? | string | '' |
listening? | boolean | false |
placeholder? | string | 'Start speaking' |
label? | string | 'Transcript' |
className? | string | '' |