KQ-1258 · LATCH/LOCK

Latch Lock

A lock toggle drawn as a padlock whose parts move on their own springs: unlocking lifts the shackle on the snap spring and swings it out about its long leg with one overshoot while the body drops a few pixels and a glint sweeps the keyhole; locking swings it back and drops it home on the flick spring against a hard stop, with a short shake through the whole lock. A disabled lock stays focusable, rattles in place and says why instead of toggling. Space and Enter toggle it through the native click, and aria-pressed reports locked.

KQ-1258 · LATCH/LOCK

Debit card

···· 4821

card locked · new payments declined

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/latch-lock

Props

pressed / defaultPressed
boolean
default true
Locked state, controlled or initial; true is locked.
onPressedChange
(locked: boolean) => void
default —
Fires from the press that changed it.
lockedLabel
string
default "Locked"
Text and accessible name while locked.
unlockedLabel
string
default "Unlocked"
Text and accessible name while unlocked; the button keeps the wider label's width.
compact
boolean
default false
Icon only, with the label as the accessible name.
weight
number
default 0.5
How heavy the lock is, 0 to 1: slower swing, deeper drop, lower thock.
rattle
number
default 0.5
How hard the lock shakes as the shackle seats and when a disabled lock is pressed.
glint
number
default 0.6
Strength of the keyhole glint on unlocking; 0 hides it.
swing
number
default 26
How far the open shackle swings out, in degrees.
size
"sm" | "md" | "lg"
default "md"
Button height 32, 40 or 48 px with the padlock scaled to match.
lockedColor
string
default "var(--accent-bright)"
The body's colour while locked and the pressed tint; any CSS colour.
unlockedColor
string
default "var(--ink-3)"
The body's colour while unlocked.
disabledNote
string
default "This lock can't be changed right now"
Spoken in a polite live region when a disabled lock is pressed.
onRefused
() => void
default —
A press on a disabled lock, after it rattled and stayed put.
sound
boolean
default false
Clack as the shackle lets go, thock as it seats, muted clacks for a refusal.
disabled
boolean
default false
Rattles instead of toggling; stays in the tab order via aria-disabled.
className
string
default —
Classes for the wrapper.