Knob
A circular rotary control for adjusting values. Perfect for audio parameters, filters, and effects — with arc indicator, pointer drag, and keyboard support.
A pure Svelte knob built from plain HTML and SVG — no external primitives. Drag up/down to adjust, use keyboard arrows for fine control, and see value progress through a 270° arc indicator. Four size variants keep it fitting everywhere from compact effect panels to large master controls.
Loading...
<script lang="ts">
import { Knob } from "$lib/components/ui/audio/elements/knob/index.js";
let value = $state(50);
</script>
<div class="flex flex-col items-center gap-4">
<Knob {value} onValueChange={(v) => (value = v)} />
<span class="text-muted-foreground text-xs tabular-nums">{value}</span>
</div> Installation
Copy and paste the following code into your project.
Usage
<script lang="ts">
import { Knob } from "$lib/components/ui/audio/elements/knob/index.js";
</script> <Knob value={50} /> Size Variants
Loading...
<script lang="ts">
import {
Knob,
type KnobSize
} from "$lib/components/ui/audio/elements/knob/index.js";
let sizes: { size: KnobSize; value: number }[] = $state([
{ size: "sm", value: 80 },
{ size: "default", value: 50 },
{ size: "lg", value: 60 },
{ size: "xl", value: 40 }
]);
</script>
<div class="flex flex-wrap items-end justify-center gap-8">
{#each sizes as item (item.size)}
<div class="flex flex-col items-center gap-2">
<Knob
size={item.size}
value={item.value}
onValueChange={(v) => {
item.value = v;
}}
/>
<span class="text-muted-foreground text-xs">{item.size}</span>
</div>
{/each}
</div> API Reference
Knob
Props
Behavior
- Drag: Click and drag vertically — drag up to increase, drag down to decrease. 200 px of travel covers the full value range.
- Keyboard:
ArrowUp/ArrowRightincreases;ArrowDown/ArrowLeftdecreases by one step.Homejumps tomin,Endtomax. - Arc indicator: A 270° SVG arc shows the track (dimmed) and the active fill from min to the current value.
- Pointer indicator: The inner disc rotates with the value, with a small dot marking the exact position.
Tip: Use
bind:valuefor two-way binding in Svelte, or passvalue+onValueChangefor a controlled setup.
Examples
Filter Control
Loading...
<script lang="ts">
import { Knob } from "$lib/components/ui/audio/elements/knob/index.js";
let frequency = $state(2000);
let resonance = $state(30);
let mix = $state(50);
function formatFreq(hz: number) {
return hz >= 1000 ? `${(hz / 1000).toFixed(1)}k` : `${hz}`;
}
</script>
<div class="flex flex-wrap items-center justify-center gap-8">
<div class="flex flex-col items-center gap-2">
<Knob
label="Freq"
value={((frequency - 20) / (20000 - 20)) * 100}
onValueChange={(v) =>
(frequency = Math.round(20 + (v / 100) * (20000 - 20)))}
size="lg"
/>
<span class="text-muted-foreground text-xs tabular-nums"
>{formatFreq(frequency)} Hz</span
>
</div>
<div class="flex flex-col items-center gap-2">
<Knob
label="Res"
value={resonance}
onValueChange={(v) => {
resonance = v;
}}
size="lg"
/>
<span class="text-muted-foreground text-xs tabular-nums">{resonance}%</span>
</div>
<div class="flex flex-col items-center gap-2">
<Knob
label="Mix"
value={mix}
onValueChange={(v) => {
mix = v;
}}
size="lg"
/>
<span class="text-muted-foreground text-xs tabular-nums">{mix}%</span>
</div>
</div> Multiple Knobs
Loading...
<script lang="ts">
import { Knob } from "$lib/components/ui/audio/elements/knob/index.js";
let channels = $state([
{ label: "Vol", value: 80 },
{ label: "Pan", value: 50 },
{ label: "EQ Lo", value: 60 },
{ label: "EQ Hi", value: 40 },
{ label: "Reverb", value: 25 },
{ label: "Delay", value: 35 }
]);
</script>
<div class="flex flex-wrap items-center justify-center gap-6">
{#each channels as channel (channel.label)}
<div class="flex flex-col items-center gap-1">
<Knob
label={channel.label}
value={channel.value}
onValueChange={(v) => (channel.value = v)}
/>
<span class="text-muted-foreground text-xs tabular-nums"
>{channel.value}</span
>
</div>
{/each}
</div> Related
- Fader — linear slider-style control for mixing boards
- Audio Player — player controls to pair with knobs
- Audio Provider — audio context and state management