KQ-1161 · TUMBLER/CODE

Tumbler Code

A one-time-code field drawn as a pin-tumbler lock: each digit raises its spring-loaded pin stack on snap to a height set by the digit, the coil compressing above it, and a paste raises them left to right on a cascade. When check accepts the code every split glides onto the shear line and the plug turns a quarter on snap with a clunk, folding the key pins away; a refused code jiggles the pins on a tween and drops them on recoil so they bounce as they land. The cells are real inputs in one tab stop: digits type in and advance, Backspace and Delete remove, arrows and Home/End move, and paste or one-time-code autofill fills them all.

KQ-1161 · TUMBLER/CODE

Coldbrook Bank texted 408 615 to •• 42.

pins set 0 of 6 · waiting for the rest

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/tumbler-code

Props

label
string
default —
What the code is for: the visible label and the name of the group of cells.
value / defaultValue
string
default ""
Controlled or initial code: digits only, never longer than length.
onValueChange
(value: string) => void
default —
Fires from the key, paste or refusal that changed the code, with the new digits.
length
number
default 6
How many digits, and so how many pins the cylinder has, 4 to 8.
brass
"brass" | "nickel" | "black"
default "brass"
The metal of the housing, the plug and the face. The pins stay nickel over brass so the split always reads.
verify
boolean
default true
Check the code when its last digit lands and turn or refuse the lock. Needs check; off, the field only collects the code.
check
(code: string) => boolean | Promise<boolean>
default —
The host's verifier. A promise holds the plug in a test turn until it settles; a rejected one leaves the pins where they are.
onComplete
(code: string) => void
default —
Fires from the key or paste that filled the last cell, with the whole code.
onResult
(accepted: boolean, code: string) => void
default —
Fires once check has answered, before the lock turns or the pins drop.
name
string
default —
The form field name; a hidden input carries the code under it.
hint
string
default —
Helper text under the cells, wired to every cell with aria-describedby.
error
string | null
default —
What is wrong, from the host: shown under the cells, marked on them with aria-invalid, and announced once.
wrongText
string
default "That code didn't turn the lock. Try again."
What a refused code says.
required
boolean
default false
Marks every cell required, so a form will not submit with an empty one.
sound
boolean
default false
Play each pin's click, the plug's clunk and the refusal's shrug. Nothing plays, and no audio context exists, unless this is on; sounds only ever answer the visitor.
disabled
boolean
default false
Disables the field and dims it.
className
string
default —
Merged onto the root element's classes.