React + TypeScript knob/fader library with a headless interaction core (rotary, relative-drag and track modes, wheel, keyboard, a11y), SVG primitives, nine prebuilt skins, seven-segment display engine, and a Vite showcase with gallery, live playground and API docs.
3.4 KiB
3.4 KiB
dreamknob
Studio-grade React knobs & faders. Rotary, linear, 2D, 3D, digital and analog — with a headless core, any number range, any decimal precision, and colors you fully control. Zero runtime dependencies.
npm install dreamknob
Quick start
import { FlatKnob } from 'dreamknob'
function Volume() {
const [value, setValue] = useState(64)
return (
<FlatKnob
size={90}
value={value}
onChange={setValue}
min={0}
max={100}
step={0.5}
label="Volume"
unit="%"
aria-label="Volume"
/>
)
}
Uncontrolled works too: pass defaultValue instead of value/onChange
(it also becomes the double-click reset target).
Interaction model
Every component shares one core:
| Gesture | Behaviour |
|---|---|
| Drag | rotary (grab & turn, follows the pointer angle), vertical, horizontal, both, or absolute track-* (faders) |
| Scroll wheel | one step per notch, Shift = fine |
↑ → / ↓ ← |
± one step (Shift = 10×) |
PageUp/PageDown |
± 10 % of range |
Home/End |
min / max |
| Double-click | reset to defaultValue |
| Touch / pen | pointer capture, touch-action: none |
All knobs render role="slider" with aria-valuemin/max/now/text.
Value handling
min/max— any numbers (negative, fractional, huge).step— decimal snap increments (0.5,0.001,1e-7…) with float-drift-safe rounding; display precision inferred automatically, overridable viadecimals.values={[0.25, 0.5, 1, 2, 4]}— discrete allowed values.steps={5}— evenly spaced detents (selector knobs).taper—linearTaper(default),logTaper(frequencies),powTaper(n)(gain), or your own{ toNormalized, fromNormalized }.onChange/onChangeStart/onChangeEnd— gesture-aware callbacks.
Prebuilt skins
import {
FlatKnob, // clean 2D arc knob (arcFrom="center" for pan knobs)
MetalKnob, // 3D brushed aluminum, knurled rim (tone="silver" | "dark")
RubberKnob, // 3D soft-touch synth knob with glow halo
VintageKnob, // chicken-head bakelite over a printed scale
LEDKnob, // segmented LED ring + true seven-segment readout
NeonKnob, // glowing arc for dark UIs
SteppedKnob, // detented selector (positions={['LP','BP','HP']})
Fader, // linear channel fader, vertical or horizontal
LEDFader, // segmented LED meter-fader with color zones
SegmentDisplay, // standalone seven-segment numeric display
} from 'dreamknob'
Every skin takes the core props plus size, label, showValue, unit, format,
and per-part color props (color, trackColor, faceColor, bodyColor, …).
Compose your own
import { Knob, Arc, Pointer, Ticks, KnobValue } from 'dreamknob'
<Knob size={96} min={-24} max={24} step={0.5} defaultValue={0} aria-label="Trim">
<Ticks count={25} activeColor="#ffd23e" />
<Arc radius={36} thickness={3} color="#ffd23e" from="center" />
<Pointer type="triangle" radius={33} length={9} width={8} color="#ffd23e" />
<KnobValue unit=" dB" />
</Knob>
<Knob> also accepts a render function: {(ctx) => <YourSVG angle={ctx.angle} />}.
Fully headless
import { useKnob } from 'dreamknob'
const { value, normalized, angle, isDragging, bind, setValue } = useKnob({
min: 0, max: 11, step: 0.1, defaultValue: 11, 'aria-label': 'Volume',
})
return <div {...bind}>…your own rendering…</div>
MIT