Knob
A rotary control for dense layouts, drawn in SVG.
Installation
$ pnpm dlx shadcn-svelte@latest add https://juddisjudd.github.io/audiocn-svelte/r/knob.json$ npx shadcn-svelte@latest add https://juddisjudd.github.io/audiocn-svelte/r/knob.json$ yarn dlx shadcn-svelte@latest add https://juddisjudd.github.io/audiocn-svelte/r/knob.json$ bunx --bun shadcn-svelte@latest add https://juddisjudd.github.io/audiocn-svelte/r/knob.jsonUsage
<script lang="ts">
import { Knob } from "#lib/components/ui/knob/index.js";
let gain = $state(0);
</script>
<Knob min={-24} max={24} origin={0} bind:value={gain} />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.
| Action | Result |
|---|---|
| Drag | Turns the knob |
| Shift+drag, Shift+wheel | Ten times finer, for precise adjustment. Press or release Shift mid-drag without a jump |
| Double-click the dial, Alt+click | Resets to resetValue |
| Double-click the value or label, Enter on the dial | Type 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.
Sizes and 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.
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".
<KnobDial>
<KnobTrack />
<KnobRange />
<KnobCap variant="mini" />
</KnobDial>Theming
| Variable or attribute | Meaning |
|---|---|
--knob-size | Set by size |
--knob-angle | The pointer angle, live, for custom skins |
data-dragging | On the dial while dragging |
data-at-origin | The value sits at origin |
--knob-cap-metal | KnobCap's metal, white by default |
--knob-cap-shade | KnobCap's shading, black by default |
--knob-cap-pitch | Spacing of KnobCap's brushed rings |
data-active | On KnobScale ticks inside the lit range |
data-major | On 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 | Default |
|---|---|---|
value Bindable. | number | resetValue ?? min |
onValueChange details.reason: drag, keyboard, wheel, reset or input. | (value, details) => void | — |
onValueCommit | (value) => void | — |
min / max | number | 0 / 100 |
step / largeStep / fineStep fineStep applies to Shift+drag, Shift+wheel and Alt+arrow. | number | 1 / 10 / step ÷ 10 |
resetValue Double-click or Alt+click restores it. | number | the first value, or min |
origin Where the arc starts; the centre for bipolar knobs. | number | min |
arc Sweep in degrees. | number | 270 |
dragDirection Circular turns the knob as you circle around it. Vertical and horizontal drag in a straight line, as in most DAWs. | "vertical" | "horizontal" | "circular" | "vertical" |
sensitivity Pixels of vertical or horizontal drag for the full range. | number | 200 |
scale | "linear" | "log" | "linear" |
allowWheel | boolean | false |
clickSound Plays a soft tick on each graduation: KnobScale's long ticks, or every largeStep without a scale. At most every 30 ms, through the shared AudioContext. | boolean | false |
format | (value: number) => string | String |
parse Reads a typed value. The default takes the first number and reads "k" as thousands. Use parsePan for pan knobs. | (text: string) => number | null | parseKnobValue |
size | "sm" | "default" | "lg" | "default" |
disabled | boolean | false |
KnobValue
| Prop | Type | Default |
|---|---|---|
editable Double-click, or Enter on the dial, to type a value. | boolean | true |
KnobScale
| Prop | Type | Default |
|---|---|---|
ticks Divisions across the arc; draws ticks + 1 marks. | number | 50 |
majorEvery Every nth tick is long. | number | 5 |
labelEvery Every nth tick is numbered. 0 hides the numbers. | number | 10 |
format | (value: number) => string | the knob's format |
KnobCap
| Prop | Type | Default |
|---|---|---|
variant default sits inside KnobScale with an indicator dot. mini fills the inside of KnobTrack with an engraved line, for small knobs. | "default" | "mini" | "default" |