Lab

Waveform

The <audio-ui-waveform> custom element of @audio-ui/elements: its attributes, its parts and a live preview.

<audio-ui-waveform> displays audio and, with a control part, seeks through it: a press seeks to the pointer, a drag scrubs, and the keyboard steps. The shape comes from the peaks property or a live levels source; the position from value or a live source, exposed as --waveform-position:

Usage

The styles read the theme's CSS variables, which Styling sets.

<style>
  audio-ui-waveform {
    display: block;
    width: 100%;
    max-width: 36rem;
  }

  audio-ui-waveform-control {
    position: relative;
    display: block;
    height: calc(var(--spacing, 0.25rem) * 20);
    border-radius: calc(var(--radius, 0.625rem) - 2px);
    background: var(--muted, oklch(0.97 0 0));
    cursor: pointer;
  }

  audio-ui-waveform-canvas {
    position: absolute;
    inset: 0;
    --waveform-progress-color: var(--primary, oklch(0.205 0 0));
    color: var(--muted-foreground, oklch(0.556 0 0));
  }

  audio-ui-waveform-region {
    top: 0;
    bottom: 0;
    background: color-mix(in oklab, var(--primary, oklch(0.205 0 0)) 10%, transparent);
  }

  audio-ui-waveform-region-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    width: calc(var(--spacing, 0.25rem) * 1);
    background: var(--primary, oklch(0.205 0 0));
    cursor: ew-resize;
  }

  audio-ui-waveform-region-handle[edge="start"] {
    left: 0;
  }

  audio-ui-waveform-region-handle[edge="end"] {
    right: 0;
  }

  audio-ui-waveform-playhead {
    top: 0;
    bottom: 0;
    width: calc(var(--spacing, 0.25rem) * 0.5);
    background: var(--foreground, oklch(0.145 0 0));
  }

  audio-ui-waveform-hover {
    top: calc(var(--spacing, 0.25rem) * -6);
    translate: -50% 0;
    padding-inline: calc(var(--spacing, 0.25rem) * 1);
    border-radius: 0.25rem;
    background: var(--popover, oklch(1 0 0));
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 10px;
    pointer-events: none;
  }
</style>

<audio-ui-waveform duration="96" value="30">
  <audio-ui-waveform-control aria-label="Seek">
    <audio-ui-waveform-canvas></audio-ui-waveform-canvas>
    <audio-ui-waveform-playhead></audio-ui-waveform-playhead>
  </audio-ui-waveform-control>
</audio-ui-waveform>

<script type="module">
  import "@audio-ui/elements/waveform";

  const waveform = document.querySelector("audio-ui-waveform");

  // Min and max pairs across the sound, from computePeaks in @audio-ui/engine/analysis.
  const peaks = [];
  waveform.peaks = peaks;
  waveform.addEventListener("input", (event) =>
    console.log(event.detail.value)
  );
</script>

API reference

pnpm add @audio-ui/elements
import "@audio-ui/elements/waveform";
ExportKindWhat it is
WAVEFORM_TAGSconstThe names the waveform's elements are registered under, frozen: a page cannot rename them by accident.
WaveformBarElementclassA bar of <audio-ui-waveform-bars>, for its index.
WaveformBarsElementclassRenders the waveform as count <audio-ui-waveform-bar> elements (24) for CSS-styled visualizers.
WaveformCanvasElementclassRenders the waveform on a canvas aligned to the device pixel grid, so it stays sharp at any density.
WaveformChangeEventtypeFired once a seek that moved the position ends.
WaveformControlElementclassThe seekable surface: a press seeks to the pointer and a drag scrubs.
WaveformControlElementEventMapinterfaceThe events a selectable waveform control fires, as addEventListener types them.
WaveformDescribetypeReturns how a position is announced.
WaveformElementclassThe root of a waveform.
WaveformElementEventMapinterfaceThe events a waveform fires, as addEventListener types them.
WaveformEventDetailinterfaceWhat a waveform's input and change events carry, besides the waveform itself as their target.
WaveformHoverElementclassShown at the hovered position while the pointer is over the control.
WaveformInputEventtypeFired on every seek.
WaveformLevelsSourcetypeA live signal: the current levels, 0…1 each, or raw samples for the scope variant.
WaveformMarkerElementclassA cue or chapter marker at value, labelled by its content.
WaveformPlayheadElementclassA non-interactive marker at the playback position.
WaveformPositionSourcetypeA live playback position, in duration units.
WaveformRangeDetailinterfaceWhat a selection's and a region's events carry: the stretch, [start, end] in duration units.
WaveformRegionElementclassA loop or selection over the waveform, from value ("start end" in duration units; the whole audio by default).
WaveformRegionElementEventMapinterfaceThe events a region fires, as addEventListener types them.
WaveformRegionHandleElementclassResizes the edge (start or end) of its region by drag or through the native <input type="range"> it contains, which receives its aria-label.
WaveformThumbElementclassA handle centered on the playback position, through --waveform-position.

Props · 8

input and change carry { value, reason }. The root carries data-active while a live signal is audible.

PartDescription
<audio-ui-waveform-control>The seekable surface, containing the native range input. getAriaValueText(value, duration) customizes its announcement. With selectable, Shift + drag selects a range and fires selectioninput and selectioncommit with [start, end]
<audio-ui-waveform-canvas>Renders on a canvas aligned to device pixels. variant (mirror, bars, line, or scope for raw samples), bar-width, bar-gap, bar-radius, min-bar-height, gain, mirrored, idle, mode (static or scrolling), scroll-speed, line-width. Colors from --waveform-color and --waveform-progress-color
<audio-ui-waveform-bars>Generates count <audio-ui-waveform-bar> elements (24), each sized by --waveform-level, for CSS-styled visualizers. Played bars carry data-played. Also gain, idle, min-level, mirrored
<audio-ui-waveform-playhead>A marker at the position
<audio-ui-waveform-thumb>A handle centered on the position
<audio-ui-waveform-hover>Shown at the hovered position; its format(value, duration) property renders it as text
<audio-ui-waveform-marker>A cue at value, labelled by its content
<audio-ui-waveform-region>A loop or selection from value ("start end"). Draggable unless movable="false". Fires regioninput and regionchange with { value, edge, reason }
<audio-ui-waveform-region-handle>Resizes the region's edge (start or end) by drag or through its native range input

The same control in React, and its parts' props: Waveform.

Built by Ouest Labs, the source code is available on GitHub.
RSS