caliper uidocs

Card vault

Pro

A virtual card screen. The number lives on the back: the card flips only after a passcode and turns itself back over after 15 seconds. Freezing tilts the card back and frosts it. The details are not on the page at all until they are revealed.

Installs components/ui/card-vault.tsxDepends on @radix-ui/react-slot, lucide-reactMotion shared motion tokens
pnpm dlx shadcn@latest add @caliper/card-vault
VIRTUAL · TEAM
4821
Mira Solheim

Card details

The number, expiry and CVC stay hidden until you confirm it is you.

Spend this month$1,240 of $2,000
  • Halden Rail$38.50
  • Notion$16
  • Fly Air Porto · return flights$184.20
  • Cafe Lumen$6.40

When to use #

Use it for

  • Showing a payment card's number, expiry and CVC behind a step-up.
  • Any sensitive reveal that should be visible as a state, not a hidden toggle.

Skip it when

  • Storing or passing card data around the page. Fetch it in onReveal and let the part drop it.
  • Secrets that are not shown on a card; use the secret field.

Decisions #

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

Behaviour

Not in the DOM until revealed
The back face is empty until onReveal succeeds, and the details are dropped when they hide, on a timer, on Hide now, or when the card is frozen.
Focus follows the reveal
Show moves focus to the passcode field, success to Hide now, and hiding returns it to Show, so it never falls to the page.

Usage

You provide the step-up
onReveal receives what was typed and returns the details or null. The library contains no passcode and no card data. The demo accepts 1234 and returns made-up numbers.

Installation #

terminal
pnpm dlx shadcn@latest add @caliper/card-vault

Adds its 7 files to components/ui/, each with its own stylesheet, and installs their packages. Pro installs with your access token, set up once per project. See Pro access. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

Import it from your copy of the source. The example behind the preview comes with the source.

example.tsx
import { CardVault } from "@/components/ui/card-vault"

The worked example comes with Pro

The 31-line example behind the preview opens here with a Pro or Team licence.

Checking your licence…

API reference #

CardVault

component
PropTypeDefaultDescription
card *CardVaultCard—
limitCardVaultLimit—
transactionsreadonly CardVaultTransaction[][]
onReveal *(passcode: string) => CardVaultDetails | Promise<CardVaultDetails | null> | null—The step-up. Receives what the person typed; return the details when it is right and null when it is not. May be async.
onFreeze((frozen: boolean) => void)—Asked for the new state; set `card.frozen` to apply it.
onCopy(() => void)—Called after the number is copied. It receives nothing, so the number never leaves the part by this route.
revealSecondsnumber15How long the details stay showing.
passcodeLengthnumber4
passcodeHintReactNode—Shown beside the passcode label, for example a hint in a demo.
format((amount: number) => string)moneyHow money is written. Defaults to US dollars.
statusDepthStatus"ready"
messagesDepthMessages—
onRetry(() => void)—
disabledboolean—
classNamestring—

Accessibility #

It exposes group, alert, timer and meter semantics, with aria-label, aria-hidden, aria-invalid, aria-describedby, aria-valuemin and aria-valuemax kept in step with state. Changes that matter are announced through a live region.

No custom key handling; Tab and the native activation keys do the work.

Motion #

Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.