Lock Open

A small, hoverable open-padlock icon. On hover (or focus) the shackle pulls upward by drawing its path to full length, and the body gives a tiny wobble-and-pop — the canonical "click to unlock" affordance. Two-state spring motion routed through SPRINGS.damped (shackle) and SPRINGS.bouncy (body), so transitions are interruptible and respect the 300ms ceiling.

Customize
Lock
28px
accent (token)

Installation

npx shadcn@latest add https://craftbits.dev/r/lock-open.json

Usage

import { LockOpen } from "@craft-bits/core/svg/lock-open";
 
<LockOpen size={28} />

Understanding the component

  1. Two-state springs, not keyframes. The icon animates between exactly two states — rest and hover. Both the body wobble and the shackle path-length interpolate via SPRINGS.bouncy / SPRINGS.damped, so hovering off mid-flight reverses the motion smoothly instead of snapping back to the rest pose.
  2. Reduced-motion fallback. When the OS-level prefers-reduced-motion setting is on — or paused is set explicitly — the icon renders the rest-state glyph with no transitions. The padlock stays legible; only the motion disappears.
  3. Hover and focus share the same trigger. Keyboard users get the same affordance as pointer users: focusing the tile triggers the same shackle-draw + body wobble.
  4. Stripped from the source. The terminal-dreams source exposed an imperative LockOpenIconHandle ref API (startAnimation / stopAnimation). The library version drops it: the ref now forwards to the underlying tile span, matching every other @craft-bits/core/svg/* primitive. Drive motion via paused instead.

Variants / Examples

// Default — uses the cb-fg foreground colour and accent token on hover.
<LockOpen />
 
// Larger glyph (the inner SVG scales — the tile stays 48px).
<LockOpen size={36} />
 
// Override the hover-border accent.
<LockOpen accentColor="#10b981" />
 
// Force the static fallback (e.g. inside a print stylesheet).
<LockOpen paused />

Props

PropTypeDefaultDescription
sizenumber28Pixel diameter of the inner SVG glyph.
accentColorstringvar(--cb-color-accent)Border tint applied on hover / focus.
pausedbooleanfalseWhen true, skip animations and render the rest-state glyph.
classNamestringExtra classes merged onto the outer tile span.
...restHTMLAttributes<HTMLSpanElement>Forwarded to the root tile span (except onMouseEnter / onMouseLeave, which the component owns).

Accessibility

  • The tile and inner SVG are marked aria-hidden="true" by default — the lock is a decorative micro-interaction. If it stands alone as a button, wrap it in a <button> with an aria-label (e.g. "Unlock entry").
  • Hover and focus both trigger the animation, so keyboard users get the same affordance as pointer users.
  • usePrefersReducedMotion short-circuits every animation when the OS-level setting is on; the icon falls back to a static glyph automatically.
  • Colour tinting flows from currentColor for the glyph and the --cb-color-accent token for the hover border, so the icon inherits whatever contrast the wrapping surface already meets.

Credits

  • Extracted from: terminal-dreams (src/components/ui/lock-open.tsx).
  • Inspiration: pqoqubbw/icons open-source animated icon set.