caliper uidocs

Live pass

Free

A credential card with a foil you check by tilting it. A sheen follows the mouse and a VERIFIED mark only shows once the card is tilted far enough, as security foil does on a banknote. A screenshot cannot show it, and the line beneath keeps a ticking clock, so a still image of the pass is obviously stale.

Installs components/ui/live-pass.tsxDepends on @radix-ui/react-slot, lucide-reactMotion honours reduced motion
pnpm dlx shadcn@latest add @caliper/live-pass
Halden LibraryMember
Mira Solheim
ID 4821 0092Valid to 09/28

Tilt the pass to check the foil · live --:--:--

onChecked has not fired yet

When to use #

Use it for

  • Member, event and access passes where showing it is live matters.
  • Demonstrating tilt-aware materials in product marketing.

Skip it when

  • Real security. This is a visible cue, not verification; check credentials on the server.
  • Anywhere the card text must stay perfectly still.

Decisions #

Why it is built this way, so you know what to keep when you change your copy.

Behaviour

Motion only when pressed
On a phone a button turns on device motion and, where the platform needs it, asks permission then. Nothing is requested on load.
Keyboard tilts it
Focus the card and press the arrow keys to tilt, Home to level. Under reduced motion the foil and mark are shown still and complete, with a note.

Usage

The credential is always text
Name, ID and expiry are real text outside the effect. The mark and foil are decoration; the live line says when the foil was checked.

Installation #

terminal
pnpm dlx shadcn@latest add @caliper/live-pass

Adds its 7 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { useState } from "react"
import { LivePass } from "@/components/ui/live-pass"

export function LivePassDemo() {
  const [checked, setChecked] = useState<string | null>(null);
  return (
    <div className="grid w-full max-w-sm gap-2">
      <LivePass title="Halden Library" kind="Member" name="Mira Solheim" id="4821 0092" validTo="09/28" onChecked={(at) => setChecked(at.toLocaleTimeString("en-GB"))} />
      <p className="m-0 text-center font-mono text-xs text-muted-foreground" aria-live="polite">{checked ? `onChecked fired at ${checked}` : "onChecked has not fired yet"}</p>
    </div>
  );
}

API reference #

LivePass

component
PropTypeDefaultDescription
title *string—The issuer, for example "Halden Library".
kindstring"Member"What the holder is, shown top right.
name *string—The holder. A long name wraps on the card.
id *string—
validTo *string—
onChecked((at: Date) => void)—Called once, the first time the card is tilted far enough to see the mark.
statusDepthStatus"ready"
messagesDepthMessages—
onRetry(() => void)—
disabledboolean—
classNamestring—

Accessibility #

It exposes group semantics, with aria-label, aria-hidden, aria-live and aria-pressed kept in step with state. Changes that matter are announced through a live region.

KeyBehaviour
←Moves to the previous item or value.
→Moves to the next item or value.
↑Moves to the previous item or value.
↓Moves to the next item or value.
HomeJumps to the first item or the minimum.

Motion #

It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.