Knob
A machined rotary control with a lit value arc and detents.
Filter
Amp envelope
Installation
npx shadcn@latest add https://neonkit.heyaadi.com/r/knob.jsonUsage
import { Knob } from "@/components/ui/knob"
<Knob label="Cutoff" defaultValue={62} />Examples
Detents and steps
Detents catch the cap while you drag or scroll, with a small spring as it lands. A knob with a dozen steps or fewer prints a mark at each one; arc narrows the sweep.
In a form
Each knob with a name submits its value through a hidden input. Double-click returns a knob to its defaultValue.
Sizes, colors and disabled
Three sizes share one drawing. Disabled knobs go dark and leave the tab order.
API reference
className and style go on the outer element. The ref and every other div attribute go on the dial, which has role="slider".
| Prop | Type | Default |
|---|---|---|
value | numberControlled value. | None |
defaultValue | numberInitial value when uncontrolled, and where a double-click returns to. | min |
onValueChange | (value: number) => voidCalled on every change while dragging, scrolling or pressing keys. | None |
onValueCommit | (value: number) => voidCalled once a drag, key press or scroll gesture ends. | None |
min | numberLowest value. When min is below zero and max above it, the ring lights outward from zero. | 0 |
max | numberHighest value. | 100 |
step | numberValues snap to multiples of step from min. | 1 |
detents | number[]Values the cap clicks into while dragging or scrolling, within 3% of the range. | None |
arc | numberDegrees of rotation from min to max, between 30 and 340. | 270 |
label | ReactNodeEngraved legend under the dial. Names the slider unless aria-label is set. | None |
showValue | booleanPrints the formatted value under the label. | false |
formatValue | (value: number) => stringFormats the printed value and aria-valuetext. | None |
name | stringSubmits the value with a form through a hidden input. | None |
color | NeonColorPalette name or hex. Falls back to --neon-accent, then cyan. | inherited |
size | "sm"Dial of 56, 80 or 112px. | "md" |
disabled | booleanDarkens the ring, blocks input and removes the dial from the tab order. | false |
Accessibility
- The dial has role="slider" with aria-valuemin, aria-valuemax, aria-valuenow, and aria-valuetext when formatValue is set.
- Arrow keys move by one step, Shift+Arrow and Page Up/Down by a tenth of the range, Home and End jump to the ends.
- Drag vertically to turn it; hold Shift for fine control or Alt for coarse.
- The wheel turns a knob once it has focus (click, drag or Tab to it) and the scroll starts over it, so a page scroll never gets caught on a knob. At either end of its travel the knob lets go and the page scrolls on.
- A visible label names the slider through aria-labelledby; pass aria-label when the legend is an abbreviation, like A, D, S and R.