KQ-1147 · ROTARY/DIAL
Rotary Dial
A number input drawn as a telephone rotary dial: put a finger in a hole and drag it clockwise to the finger stop, and the wheel turns 1:1 with the pointer, ratcheting as it winds and giving only a few degrees at rest and at the stop. Let go at the stop and it winds back at the constant speed a governor holds, a linear run at returnSpeed pulses a second rather than a spring, ticking once per pulse while the next slot counts them up; it knocks against its rest stop on a stiff, loose spring and the digit lands with a flick. The holes are real buttons in one tab stop: arrows move round the dial, Enter or Space dials the focused hole, number keys dial directly (queued while it is busy), Backspace removes a digit and Escape clears.
555 · 3 of 7 digits
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/rotary-dial
Props
- value / defaultValue
- string
- default ""
- The number dialled so far, digits only; anything longer than digits is cut. Controlled or uncontrolled.
- onValueChange
- (value: string) => void
- default —
- Fires with the whole number when a digit lands, on Backspace and on clear.
- onComplete
- (value: string) => void
- default —
- Fires when the digit that fills the last slot lands.
- label
- string
- default —
- What is being dialled: the dial's accessible name.
- returnSpeed
- number
- default 10
- How fast the wheel winds back, in pulses per second (30° each), 6 to 20: the pace of the pulse ticks and of the counting slot.
- finish
- "bakelite" | "chrome"
- default "bakelite"
- A glossy black wheel over a cream plate with black digits, or a spun-metal wheel over a black plate with white digits. Physical colours mixed from black, white and the theme's ink, so the dial reads the same on a light or dark page.
- digits
- number
- default 7
- How many digits the number has, 3 to 10: the slot count. When every slot is full the holes stop engaging and number keys are ignored.
- display
- boolean
- default true
- Show the number above the dial in slots, with a clear button and a polite live region. Off, only the dial renders and the host shows and announces the number.
- sound
- boolean
- default false
- A ratchet tick every 10° as the wheel winds, rising as it goes, a clack at the finger stop, a tick per pulse on the way back and a knock when it comes to rest. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the dial, disables its holes and the clear button, and ignores drags and keys.
- className
- string
- default —
- Merged onto the root's classes.
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue | string | "" | The number dialled so far, digits only; anything longer than digits is cut. Controlled or uncontrolled. |
| onValueChange | (value: string) => void | — | Fires with the whole number when a digit lands, on Backspace and on clear. |
| onComplete | (value: string) => void | — | Fires when the digit that fills the last slot lands. |
| label | string | — | What is being dialled: the dial's accessible name. |
| returnSpeed | number | 10 | How fast the wheel winds back, in pulses per second (30° each), 6 to 20: the pace of the pulse ticks and of the counting slot. |
| finish | "bakelite" | "chrome" | "bakelite" | A glossy black wheel over a cream plate with black digits, or a spun-metal wheel over a black plate with white digits. Physical colours mixed from black, white and the theme's ink, so the dial reads the same on a light or dark page. |
| digits | number | 7 | How many digits the number has, 3 to 10: the slot count. When every slot is full the holes stop engaging and number keys are ignored. |
| display | boolean | true | Show the number above the dial in slots, with a clear button and a polite live region. Off, only the dial renders and the host shows and announces the number. |
| sound | boolean | false | A ratchet tick every 10° as the wheel winds, rising as it goes, a clack at the finger stop, a tick per pulse on the way back and a knock when it comes to rest. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the dial, disables its holes and the clear button, and ignores drags and keys. |
| className | string | — | Merged onto the root's classes. |