Introduction
Headless React components for audio apps, in the style of Base UI.
General UI libraries stop where music software starts. A volume fader is not a range input: it has a dB law, goes down to −∞, resets on double-click and moves in fine steps with Shift. A row of steps is not a list of checkboxes: you drag across it to set sixteen at once. And 64 meters running at 60 frames per second cannot go through React state.
daw-ui does this part, and leaves the looks to you:
- DAW input: relative vertical drag, Shift for fine steps, double-click and Delete to reset, the mouse wheel, optional pointer lock, and typed values with units ("1k", "-6 dB", "50L").
- Painting: drag across toggles to set them all. Fast drags do not skip steps, and lanes keep a stroke on one row of a mixer.
- Gestures: every user action is wrapped in
onGestureStart/onGestureEnd, so it becomes one undo step or one automation pass. - Measured performance: meters never render through React, and budgets on React commits and bundle size fail CI.
- Accessible, in any language: correct roles,
aria-valuetextas users read it, a keyboard path for everything, numbers in the user's locale, and right-to-left layouts. - Headless, like Base UI: parts,
data-*attributes, CSS variables and arenderprop. Style it with Tailwind, CSS, or a shadcn registry of your own.
Installation
npm install @addstack/daw-uiIt needs React 19. The core (@addstack/daw-ui: ranges, scales, formats, meter ballistics) has no dependencies; the components are in @addstack/daw-ui/react.
Quick start
Each component is a set of parts. Put them together, style them with classes and the data-* attributes they set, and connect the value to your audio:
import { formats, scales } from '@addstack/daw-ui';
import { Knob } from '@addstack/daw-ui/react';
export function Cutoff({ filter }: { filter: BiquadFilterNode }) {
return (
<Knob.Root
min={20}
max={20_000}
defaultValue={20_000}
scale={scales.log}
format={formats.frequency()}
onValueChange={(hz) => filter.frequency.setTargetAtTime(hz, filter.context.currentTime, 0.01)}
>
<Knob.Label>Cutoff</Knob.Label>
<Knob.Control className="size-12">
<svg viewBox="0 0 100 100">
<Knob.Track className="fill-none stroke-neutral-800 stroke-9" />
<Knob.Range className="fill-none stroke-orange-500 stroke-9" />
<Knob.Pointer className="stroke-white stroke-7" from={10} to={28} />
</svg>
</Knob.Control>
<Knob.Value />
</Knob.Root>
);
}Components
Knob, Fader, Slider, XYPad, BarGraph, NumberBox, Meter, Spectrum, Toggle, ToggleGroup, Keys, Timeline, Region, Waveform, Notes and Curve, with live demos and their props.
Blocks
An arrangement, a piano roll, a mixer, a multiband crossover, tuners and an ADSR envelope, composed from the components, to copy and adapt.
Styling
Data attributes, CSS variables, the render prop, and building a shadcn registry.
Principles
Accessibility, no hard-coded English, right-to-left layouts, measured performance.
Playground
A drum machine and mixer built from these components, with Web Audio.