docs / core / knob

Knob

one number, set by turning: a level, a mix, a gain. it earns its circle when several sit in a row and get balanced against each other. for a single value in a settings list, Slider reads faster.

intensity · recedesrsc · client

provenance

authored in usva

layer

core / primitives

intensity

recedes · safe anywhere, including dense surfaces

composition

banks of related values tuned against one anotherdrag the ring to dial it, or the body left and right to scrub. hold shift on either for fine controlpair label with showValue so the number survives the dragonValueCommitted to persist, onValueChange to previewnot a dial for one lonely setting. that is a Slidernot a readout. Progress and StatChip display, this one accepts

a11y

role="slider" named by its label · arrows step, Home and End reach the bounds, PageUp and PageDown move by ten, shift gives a tenth · the dial takes the focus ring, and the whole square is the hit target · no wheel handler, so scrolling the page over it stays scrolling the pagejest-axe

dependencies

class-variance-authority
live demo · try it out
Gain
6 dB
customize
labeltext above the dial
sizesm is for dense rows
minlower bound
-12
maxupper bound
12
stepincrement per tick
3
defaultValuestarting angle
6
suffixunit appended to the readout
showValuevalue readout under the dial
disableddims and ignores input
usagecopy
import { Knob } from "@usva-ui/react/primitives/knob";

<Knob
  label="Gain"
  defaultValue={6}
  min={-12}
  max={12}
  step={3}
  showValue
  formatValue={(v) => `${v} dB`}
/>

props

proptypedefaultnotes
valuenumbercontrolled value.
defaultValuenumberinitial value when uncontrolled.
onValueChange(value: number) => voidfires on every change, mid-drag and per key press.
onValueCommitted(value: number) => voidfires once the pointer or key is released. use this to persist.
minnumber0lower bound.
maxnumber100upper bound.
stepnumber1increment per arrow key press, and the grid every drag snaps to.
disabledbooleanfalsedims to 50% and ignores pointer and keyboard.
labelReactNodelabel above the dial. also names the knob for screen readers.
showValuebooleancurrent value under the dial, in mono with tabular figures.
formatValue(value: number) => stringformats the readout and the value announced to screen readers.
size"sm" | "md" | "lg""md"dial diameter, 44 / 64 / 96px.

get it

bun add @usva-ui/reactcopy
usagecopy
import { Knob } from "@usva-ui/react/primitives/knob";

<Knob label="Volume" defaultValue={59} showValue formatValue={(v) => `${v} %`} />