PParable
All components

Waveform Scrubber

Interactive

A 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.json

Runs 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">

PropTypeDefaultDescription
peaksnumber[]Explicit peak amplitudes (0–1). When provided, wins over `seed`.
seednumber1Seed for the procedural waveform. Deterministic across SSR and client.
durationnumber180Total duration in seconds.
currentTimenumberControlled playhead position in seconds. When set, the internal transport stops self-advancing — drive time from the parent and listen to `onSeek`.
defaultTimenumber0Initial playhead position (uncontrolled), in seconds.
playingbooleanControlled playing state. Pair with `onPlayPause`.
defaultPlayingbooleanfalseInitial playing state (uncontrolled).
onSeek(seconds: number) => voidFires with the target time (seconds) on every user seek: click, drag, or keyboard.
onPlayPause(playing: boolean) => voidFires with the requested state when the user toggles play/pause, and with `false` when playback reaches the end.
accentColorstring"var(--foreground, #171717)"Played-region / playhead colour. Any CSS colour, `var()` welcome.
inactiveColorstring"var(--muted-foreground, #8a8a8a)"Unplayed-region colour. Any CSS colour, `var()` welcome.
heightnumber96Waveform height in px.
barWidthnumber3Width of each waveform bar in px.
barGapnumber2Gap between bars in px.
hideControlsbooleanfalseHide the play button + time readout row.
labelstring"Audio position"Accessible label for the scrub surface.