audiocnSolid

Knob

A rotary control for dense layouts, drawn in SVG.

0 dBGain
CPan
120Low cut

Installation

$ pnpm dlx shadcn@latest add @audiocn-solid/knob

Usage

import { Knob, KnobDial } from "@/components/ui/knob";
import { createClickSound } from "@/lib/audio/click";
<Knob min={-24} max={24} origin={0} value={gain} onValueChange={setGain} />

Customize the optional detent tick by passing a ClickSound:

const softTick = createClickSound({
  tone: { hz: 900, decayMs: 2, gain: 0.8 },
  noise: { decayMs: 0.5, gain: 0.1 },
  lengthMs: 8,
  volume: 0.2,
});

<Knob clickSound={softTick}>
  <KnobDial />
</Knob>;

Drag the dial up to increase the value and down to decrease it. Set dragDirection="circular" to turn it by circling around the dial, clockwise to increase and anticlockwise to decrease.

ActionResult
DragTurns the knob
Shift+drag, Shift+wheelTen times finer, for precise adjustment. Press or release Shift mid-drag without a jump
Double-click the dial, Alt+clickResets to resetValue
Double-click the value or label, Enter on the dialType a value; Enter applies it, Escape cancels

The value keeps one width across the whole range, so the layout never moves while you turn it.

Anatomy

<Knob>
  <KnobDial>
    <KnobTrack />
    <KnobRange />
    <KnobPointer />
  </KnobDial>
  <KnobValue />
  <KnobLabel />
</Knob>

KnobTrack, KnobRange and KnobPointer are SVG elements inside a 100 × 100 view box, so you can add your own shapes next to them. KnobScale and KnobCap are another set of parts for the same dial, shown in the volume dial and the metal knobs.

Examples

Drag directions

Choose dragDirection to match how you want to move the dial:

  • vertical, the default: drag up to increase the value, down to decrease it. The cursor shows an up/down arrow while dragging.
  • horizontal: drag right to increase the value, left to decrease it. The cursor shows a left/right arrow while dragging.
  • circular: turn clockwise to increase the value, anticlockwise to decrease it.

Hold Shift for finer control in all three modes. For vertical and horizontal drags, sensitivity sets the distance in pixels for the full range. The default is 200.

0.0 dBVertical
0.0 dBHorizontal
0.0 dBCircular

Sizes and disabled

sm
default
lg
disabled

Volume dial

A hi-fi volume dial: KnobScale draws numbered ticks around the dial and KnobCap a brushed aluminium cap with an indicator dot. Give it room for the numbers with a larger --knob-size. clickSound adds a soft tick on each long graduation.

Volume

Ticks between origin and the value light up, so a bipolar knob lights from its centre. The ticks are spread evenly along the arc, so they follow scale="log" too.

Metal knobs

The same aluminium at everyday sizes: swap KnobPointer for <KnobCap variant="mini" />. The mini cap fills the inside of KnobTrack and marks the value with an engraved line, which still reads at size="sm".

0 dBGain
CPan
120Low cut
65%Mix
<KnobDial>
  <KnobTrack />
  <KnobRange />
  <KnobCap variant="mini" />
</KnobDial>

Theming

Variable or attributeMeaning
--knob-sizeSet by size
--knob-angleThe pointer angle, live, for custom skins
data-draggingOn the dial while dragging
data-at-originThe value sits at origin
--knob-cap-metalKnobCap's metal, white by default
--knob-cap-shadeKnobCap's shading, black by default
--knob-cap-pitchSpacing of KnobCap's brushed rings
data-activeOn KnobScale ticks inside the lit range
data-majorOn KnobScale's long ticks

Style the SVG parts with stroke-* and fill-* classes. Restyle the lit ticks from the scale, for example <KnobScale class="**:data-active:stroke-primary" />.

Accessibility

The dial is a focusable slider with aria-valuetext from format, named by KnobLabel. It supports the same keys as the fader, and Enter opens the value editor.

API reference

Prop

Type

KnobValue

Prop

Type

KnobScale

Prop

Type

KnobCap

Prop

Type