Plot

Curves and draggable points, for equalizers, filters and compressors.

Audio UI

Installation

pnpm dlx shadcn@latest add @audio-ui/plot

It installs the element alone. For the equalizer above, with its pink noise and spectrum, ready to run: npx shadcn@latest add @audio-ui/plot-demo.

Anatomy

Import the primitive and assemble its parts.

import { Plot } from "@audio-ui/react";

<Plot.Root>
  <Plot.Grid />
  <Plot.Graph>
    <Plot.Curve />
    <Plot.Trace />
    <Plot.Line />
    <Plot.Band />
  </Plot.Graph>
  <Plot.Mark />
  <Plot.Dot />
  <Plot.Cursor>
    <Plot.CursorReadout />
  </Plot.Cursor>
  <Plot.Handle />
</Plot.Root>

Usage

import {
  Plot,
  PlotArea,
  PlotCurve,
  PlotGraph,
  PlotGrid,
  PlotHandle,
} from "@/components/audio-ui/plot";
import { eqResponse } from "@audio-ui/core/analysis";

<Plot minX={20} maxX={20000} minY={-18} maxY={18} scaleX="log">
  <PlotGrid x={{ count: 6 }} y={{ ticks: [-12, 0, 12] }} />
  <PlotGraph>
    <PlotArea fillTo={0} fn={response} />
    <PlotCurve fn={response} />
  </PlotGraph>
  <PlotHandle
    aria-label="Band 1"
    onValueChange={({ x, y }) => setBand({ frequency: x, gainDb: y })}
    value={{ x: band.frequency, y: band.gainDb }}
  />
</Plot>;

fn is y = fn(x) in the axes' units. @audio-ui/core/analysis gives you the functions for the usual curves: eqResponse, biquadResponse and compressorOutput (and webAudioCompressorOutput, the curve of the browser's own compressor node), and for keeping a band's handle on the curve, bandHandleDb (where it sits) and bandGainForHandle (the gain that puts it where the pointer is).

Handles

A handle holds a native <input type="range"> per axis, so it works from the keyboard: the arrow keys move it by a hundredth of the axis, a tenth with Shift, and Home / End go to the ends. Dragging moves it from where it is rather than jumping to the pointer, and four times finer with Shift. A double click, an Alt + click or Delete return it to defaultValue, or the middle of the plot (reason: "reset"). axis="x" or axis="y" holds it to one axis.

Live signals

PlotTrace draws a list of y values from a source straight in the DOM, with no React render per frame: the spectrum of the sound behind an equalizer, on a scale of its own (min, max). PlotDot is a point that follows a live { x, y }, such as the input level riding a compressor's curve. The use-spectrum hook turns an AnalyserNode into the source a trace wants, resampled onto a logarithmic frequency axis, and the default example plays pink noise through the equalizer so you hear what you draw.

const spectrum = useSpectrum(analyser, { minHz: 20, maxHz: 20000 });

<PlotGraph>
  <PlotTraceArea fillTo={-100} min={-100} max={-10} source={spectrum} />
  <PlotCurve fn={response} />
</PlotGraph>;

The hook's options are in Analysis.

Examples

Filter

One handle on the resonance peak sets the cutoff and how much it rings.

Audio UI

Compressor

One handle sets the threshold, the other the ratio.

Audio UI

API reference

Root

Groups the parts of a plot and owns its two axes: the range of each and how values spread along it, evenly or logarithmically, the way frequency is drawn. Everything placed on the plot (curves, lines, bands, handles) is placed in the axes' units. Renders a <div> element.

Props · 7

Data attributes · 1

data-disabled
Present when disabled.

Band

A stretch of the plot between two values on one axis, across the whole of the other: the frequencies a sweep can reach, the levels over a threshold. Sits in Plot.Graph. Renders a <rect> element.

Props · 3

Data attributes · 1

data-disabled
Present when disabled.

Dot

A point on the plot that nothing drags: where the signal is right now, such as the input level on a compressor's curve. Give it a source and it moves straight in the DOM without re-rendering React, or a value for a still point. Hidden from assistive technology and from the pointer. Renders a <div> element.

Props · 2

Data attributes · 1

data-disabled
Present when disabled.

Cursor

Follows the pointer over the plot, for crosshair lines and a readout of what is under it. It covers the plot, lets pointer events through, and sets --plot-cursor-x and --plot-cursor-y (0% to 100% across and down) and data-active while the pointer is over the plot with a mouse or a pen, all in the DOM without re-rendering React. Put lines in it that use the two variables, and a Plot.CursorReadout. Renders a <div> element.

Data attributes · 1

data-disabled
Present when disabled.

CursorReadout

The value under the pointer, as text: format turns it into what to show, and the text is written straight into the DOM as the pointer moves. It sits where the pointer is; set its offset and its look with your own classes. Renders a <div> element.

Props · 1

Data attributes · 1

data-disabled
Present when disabled.

Grid

Grid lines and their labels, drawn from the axes: round values along each axis you give, so you do not place each line and label by hand. It covers the plot, is hidden from assistive technology and from the pointer, and marks its parts for styling: data-part="line" and data-part="label", each with data-axis, and data-zero on the line at zero. Renders a <div> element.

Props · 2

Data attributes · 1

data-disabled
Present when disabled.

Handle

A point on the plot that can be moved: an equalizer band at its frequency and gain, a filter's cutoff and resonance, a compressor's threshold. Its value is in the axes' units, and axis can hold it to one of them. Dragging moves it from where it is, never jumping to the pointer, four times finer with Shift. A double click, an Alt + click or the Delete key return it to defaultValue, or the middle of the plot. It holds a native <input type="range"> per axis it moves along, carrying the accessible names: the first takes focus, and the arrow keys move it by a hundredth of the axis, a tenth with Shift. Renders a <div> element.

Props · 8

Data attributes · 2

data-disabled
Present when disabled.
data-dragging
Whether a pointer is dragging the handle.

Graph

The drawing surface: an <svg> covering the plot, stretched to its size, that Plot.Curve, Plot.Line and Plot.Band draw in. Strokes keep their width however the plot is stretched. Hidden from assistive technology and from the pointer. Renders a <svg> element.

Data attributes · 1

data-disabled
Present when disabled.

Trace

A live line across the plot: the list of y values a source holds, such as the spectrum of the sound, spread evenly across the x axis. It is drawn straight in the DOM each time the source changes, without re-rendering React, so it can follow audio frame by frame. With fillTo, it closes down to that y value to be filled as an area. Sits in Plot.Graph. Renders a <path> element.

Props · 4

Data attributes · 1

data-disabled
Present when disabled.

Curve

A curve across the whole plot: y = fn(x) in the axes' units, such as an equalizer's response in dB at each frequency. With fillTo, it closes down to that y value, to be filled as an area. Sits in Plot.Graph. Renders a <path> element.

Props · 3

Data attributes · 1

data-disabled
Present when disabled.

Line

A straight line across the plot at a value: vertical at an x value, such as a filter's cutoff, or horizontal at a y value, such as 0 dB. Sits in Plot.Graph. Renders a <line> element.

Props · 2

Data attributes · 1

data-disabled
Present when disabled.

Mark

A label at a value on one axis, such as "1k" under a frequency or "+12" by a gain: placed at the value along the axis and left to you to set apart from the plot's edge. Hidden from assistive technology, which reads the handles' own values. Renders a <div> element.

Props · 2

Data attributes · 1

data-disabled
Present when disabled.

Registry component

PlotCursor takes a format function, (value) => string, for its readout; PlotTraceArea is a Trace drawn as a filled area. The rest take the primitive's props.

More Shadcn Plot components

Browse 22 production-ready audio/ui Plot components for players, mixers, and synth interfaces. These examples use the headless primitives from @audio-ui/react and stay fully compatible with Shadcn Create so radius, color, and typography match your configured theme.

Browse all 22 Shadcn Plot components for copy-ready layouts, dashboards, and forms built with Tailwind CSS in the audio/ui library.

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