Fader
faderControlsA recessed groove, a lit fill, and a grippy cap. Pressing anywhere on the track jumps the cap to that spot and keeps dragging from there — absolute positioning, the way a real mixer behaves — while Shift switches to a relative fine pass without yanking the cap under the cursor. Optional tick marks take either a count or explicit values, so a dB scale lands where the numbers actually are. Six variants re-skin it from a moulded cap to a console blade, a cream vintage face or a capless hairline.
default
flat
channel
vintage
minimal
neon
Out
0.0 dB
Send
25%
Mix
50%
Install
Copies the source into your project. Anything it depends on comes with it.
$ npx shadcn add @syntho-ui/faderPulls in
fader-headlessuse-surface-pointeruse-wheeluse-first-interactionknob-corecontrol-skincontrol-labelcontrol-mathcontrol-formatcontrol-themeuse-control
First time? Add the registry to your components.json once:
{
"registries": {
"@syntho-ui": "https://engine.syntho.app/r/{name}.json"
}
}Usage
Controlled or uncontrolled, whichever suits the surrounding state.
import { Fader } from "@/components/ui/fader"
import { decibels } from "@/lib/format"
<Fader
label="Out"
min={-60}
max={6}
defaultValue={0}
format={decibels()}
ticks={[6, 0, -6, -12, -24, -60]}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | number | — | Controlled value. Omit to let the control own its state. |
| defaultValue | number | 0 | Starting value when uncontrolled, and the double-click reset target. |
| onChange | (value: number) => void | — | Fires on every value change, in both controlled and uncontrolled modes. |
| onChangeEnd | (value: number) => void | — | Fires once when a drag gesture finishes — the hook for undo coalescing. |
| min | number | 0 | Lower bound of the range. |
| max | number | 1 | Upper bound of the range. |
| step | number | 0 | Quantisation grid. 0 means continuous. |
| label | string | — | Caption above the control. Doubles as the accessible name. |
| unit | string | — | Suffix appended by the default formatter, e.g. "Hz". |
| format | (value: number) => string | — | Custom readout formatter. Overrides `unit`. |
| hideValue | boolean | false | Hide the numeric readout. |
| disabled | boolean | false | Block interaction and dim the control. |
| variant | "default" | "flat" | "channel" | "vintage" | "minimal" | "neon" | "default" | Visual preset. flat is a matte cap over a solid fill, channel is the long thin blade of a console strip, vintage a cream knurled cap, minimal drops the cap for a hairline at the value, and neon keeps the fill glowing at rest. Looks only — every variant behaves identically. An explicit variant wins over an inherited skin. |
| skin | "default" | "flat" | "vintage" | "minimal" | "neon" | — | Finish, shared with every other control in the kit. Omitted, the fader takes whatever a surrounding ControlSkinProvider declares. |
| orientation | "vertical" | "horizontal" | "vertical" | Which way the fader travels. |
| length | number | 140 | Long axis in pixels. |
| thickness | number | 34 | Short axis in pixels — the width of the cap. |
| ticks | number | number[] | — | A count for evenly spaced ticks, or explicit values in the control's own units. |
| wheelSensitivity | number | 1/70 ≈ 0.0143 | Normalised units per wheel notch. The default crosses a continuous range in about 70 notches and guarantees one declared step per notch for stepped ranges; 0 disables the wheel. |
| onInteraction | (event) => void | — | Fires once, on the first gesture, synchronously inside the event — for resuming a suspended AudioContext. |
Interaction
- Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
- Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
- Double-click resets to
defaultValue. - Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
- Proper
sliderandswitchroles with livearia-valuetext, so a screen reader announces the formatted value rather than the raw number. - The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.