Knob
Rotary knob/dial: APG slider semantics with angle-mapped pointer dragging.
|
|
| Package |
@vizejs/ui/knob |
| Maturity |
stable |
| Own the source |
vize lib pull knob |
| Requires |
controllable-state, id |
| Aliases |
knob, dial, rotary input, potentiometer |
| Covers |
WAI-ARIA Slider, React Aria useSlider (rotary), Web Audio UI knobs |
Usage
import { Knob } from "@vizejs/ui/knob";
Or copy the source into your project with vize lib pull knob (see Source Distribution).
API
Knob
Source: src/families/form/knob/knob.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Element id. null and undefined select a deterministic fallback. |
name |
string |
undefined |
Native form field name; a hidden input submits the value. |
modelValue |
number |
undefined |
Controlled value. undefined selects uncontrolled behavior. |
defaultValue |
number |
min |
Initial uncontrolled value, also restored by form reset. |
min |
number |
0 |
Lower bound. |
max |
number |
100 |
Upper bound (repaired to min + 1 when not greater than min). |
step |
number |
1 |
Positive step. |
largeStep |
number |
step * 10 |
Positive step for Page Up and Page Down. |
startAngle |
number |
-135 |
Indicator angle of min, in degrees clockwise from 12 o'clock. |
endAngle |
number |
135 |
Indicator angle of max; the sweep must be positive and at most 360°. |
allowWheel |
boolean |
false |
Opt in to wheel stepping while focused. |
disabled |
boolean |
false |
Disable interaction and form submission. |
readOnly |
boolean |
false |
Keep focus and form value while preventing user changes. |
getValueText |
(value: number) => string |
undefined |
Formats aria-valuetext, for example (v) => \${v} dB``. |
ariaLabel |
string |
undefined |
Accessible name when no label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Ids that label the knob. |
ariaDescribedby |
string |
undefined |
Ids that describe the knob. |
ariaErrormessage |
string |
undefined |
Id of the validation error message used while invalid. |
ariaInvalid |
KnobAriaInvalid |
false |
Invalid state announced to assistive technology. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: number] |
Fired for every requested value, including drag frames. |
change |
[value: number, source: KnobChangeSource] |
Fired once a change is committed (key press, pointer release, wheel, or API). |
Slots
| Slot |
Slot props |
Description |
default |
KnobSlotState |
Renders the dial face and indicator with the angle and value. |
Exposed
| Member |
Type |
Description |
value |
number |
Current value. |
angle |
number |
Indicator angle in degrees (clockwise from 12 o'clock). |
percent |
number |
Position within the bounds, 0–100. |
min |
number |
Normalized lower bound. |
max |
number |
Normalized upper bound. |
dragging |
boolean |
Whether a pointer drag is active. |
disabled |
boolean |
Whether interaction is disabled. |
state |
KnobState |
Stable state token. |
element |
HTMLSpanElement | null |
Rendered role="slider" element. |
focus |
(options?: FocusOptions) => void |
Focus the rotary element. |
setValue |
(value: number) => boolean |
Request a value (snapped/clamped or wrapped); returns whether it changed. |
reset |
() => boolean |
Restore the default value; returns whether it changed. |
Behavior
Normative state x input -> outcome table for knob.vue (@vizejs/ui/knob), a
rotary control with WAI-ARIA APG slider semantics. Angles are degrees clockwise
from 12 o'clock over a sweep (default -135° to 135°). Every row is proven by the
named test in knob.test.ts or knob-ssr.test.ts; compile-only assertions live
in knob.types.test-d.ts.
| # |
State |
Input |
Outcome |
Proven by |
| K1 |
geometry |
angle <-> value |
values map linearly onto the sweep; pointer angles in the dead zone resolve to the nearer end (no jump across ends) |
maps angles and values with a dead zone that never jumps across ends |
| K2 |
named |
render |
focusable role="slider" with aria-valuenow/min/max/valuetext, --vize-knob-angle/--vize-knob-percent, hidden value |
renders an APG slider with angle hooks and a hidden form value |
| K3 |
focused |
Arrow / Page / Home / End |
Up/Right increase, Down/Left decrease, pages use largeStep, Home/End jump to bounds; each distinct change commits |
keyboard steps, pages, and jumps to bounds, committing each change |
| K4 |
idle |
pointer drag |
press focuses and maps the pointer angle around the center; moves update the value; release commits once |
dragging rotates around the center and commits once on release |
| K5 |
wheel / locked |
wheel, keys, pointer |
wheel is opt-in and needs focus; disabled and read-only knobs ignore input and emit nothing |
wheel is opt-in and needs focus; disabled and read-only knobs ignore input |
| K6 |
controlled / form |
keys, reset, API |
controlled values win; the hidden input submits and form reset restores defaultValue; setValue snaps; reset, focus |
controlled values, form reset, and the imperative API |
| K7 |
SSR / hydration |
isolated requests |
byte-identical markup with the CSS angle and no NaN/Infinity; hydration without diagnostics |
renders byte-identical rotary markup and hydrates without mismatches |
Public extension contract
| Surface |
Contract |
| Parts |
root (the role="slider" element; the slot draws the face). |
| Data attributes |
data-vize-ui="knob", data-state (idle/dragging/readonly/disabled). |
| CSS custom properties |
--vize-knob-angle (deg) and --vize-knob-percent. |
The subpath is tree-shakable and ships no CSS; those package contracts are
pinned by distribution.test.ts, check:size, and check:tree-shaking.