Audio waveform
A stylised playback scrubber for voice moments. A row of vertical bars carries a playhead, and each bar can hold its own tone so a transcript reads by speaker or category. Non-interactive by default; pass onSeek to opt into a slider that supports tap, drag scrubbing (mouse or touch), and arrow-key nudging.
Interactive
Tap or drag to scrub. Focus and use ← / → to nudge (Shift for 10%, Home / End for the extremes).
const [progress, setProgress] = useState(0.35);
<AudioWaveform bars={bars} progress={progress} onSeek={setProgress} ariaLabel="Voice moment scrubber" ariaValueText={`${fmt(position)} of ${fmt(duration)}`}/>Passing onSeek promotes the bar to role="slider" with aria-valuenow / min / max. Give it an ariaValueText for a human-readable position.
Read only
<AudioWaveform bars={[0.3, 0.5, 0.9, ...]} progress={0.6} ariaValueText="01:12 of 02:00" />With no onSeek the waveform renders as an img named by ariaValueText. Bars accept plain numbers or { value, tone } objects.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
bars | Array<{ value: number; tone?: BadgeTone } | number> | — | Sampled amplitudes 0–1; per-bar tone tints the played portion. |
progress | number | — | Playback position 0–1; clamped. |
onSeek | (fraction: number) => void | — | Enables slider semantics, tap-and-drag scrubbing, and keyboard nudging. |
ariaLabel | string | 'Audio scrubber' | Slider name for AT. |
ariaValueText | string | — | Human-readable position, e.g. "08:10 of 08:19". |