Waveform Scrubber
InteractiveA seekable audio-waveform scrubber on canvas: deterministic seeded peaks (or your own peak data), a simulated transport with play/pause and elapsed/total readouts, pointer-capture drag seeking, and full keyboard control on a role="slider" surface. Under prefers-reduced-motion the animation loop is disabled and the playhead steps once per second.
Inspired by Extracted from the Earshot template — independently built, not affiliated. Attribution policy
0:003:34
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/waveform-scrubber.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/waveform-scrubber.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="w-full max-w-md px-4">
<WaveformScrubber seed={7} duration={214} label="Scrub episode 14" />
</div>Props
WaveformScrubberProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">
| Prop | Type | Default | Description |
|---|---|---|---|
| peaks | number[] | — | Explicit peak amplitudes (0–1). When provided, wins over `seed`. |
| seed | number | 1 | Seed for the procedural waveform. Deterministic across SSR and client. |
| duration | number | 180 | Total duration in seconds. |
| currentTime | number | — | Controlled playhead position in seconds. When set, the internal transport stops self-advancing — drive time from the parent and listen to `onSeek`. |
| defaultTime | number | 0 | Initial playhead position (uncontrolled), in seconds. |
| playing | boolean | — | Controlled playing state. Pair with `onPlayPause`. |
| defaultPlaying | boolean | false | Initial playing state (uncontrolled). |
| onSeek | (seconds: number) => void | — | Fires with the target time (seconds) on every user seek: click, drag, or keyboard. |
| onPlayPause | (playing: boolean) => void | — | Fires with the requested state when the user toggles play/pause, and with `false` when playback reaches the end. |
| accentColor | string | "var(--foreground, #171717)" | Played-region / playhead colour. Any CSS colour, `var()` welcome. |
| inactiveColor | string | "var(--muted-foreground, #8a8a8a)" | Unplayed-region colour. Any CSS colour, `var()` welcome. |
| height | number | 96 | Waveform height in px. |
| barWidth | number | 3 | Width of each waveform bar in px. |
| barGap | number | 2 | Gap between bars in px. |
| hideControls | boolean | false | Hide the play button + time readout row. |
| label | string | "Audio position" | Accessible label for the scrub surface. |