caliper uidocs

Steps block

Block

How it works, step by step, with an honest time and what exists after each step.

Installs components/ui/steps-block.tsxDepends on lucide-reactMotion shared motion tokens
pnpm dlx shadcn@latest add https://caliperui.site/r/steps-block.json

How it works

From bank feed to closed books

Seven minutes of setup, then Halden works overnight. Choose a step to see what exists after it.

Mercury connected · 2,184 lines imported2 min

When to use #

Use it for

  • Setup or onboarding that takes a few clear steps.
  • Buyers worry about switching cost.

Skip it when

  • More than five steps; link to the guide.
  • Steps without an outcome; describe the result instead.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/steps-block.json

Adds its 4 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 { type ReactNode } from "react"
import { StepsBlock } from "@/components/ui/steps-block"

function Frame({ children }: { children: ReactNode }) {
  return <div className="w-full overflow-hidden rounded-[14px] shadow-[0_0_0_1px_var(--border)]">{children}</div>;
}

const steps: Parameters<typeof StepsBlock>[0] = { eyebrow: "How it works", title: "From bank feed to closed books", lead: "Seven minutes of setup, then Halden works overnight. Choose a step to see what exists after it.", steps: [
    { title: "Connect your bank", time: "2 min", body: "Read-only access through Plaid.", artefact: <><span className="text-sm">Mercury connected · 2,184 lines imported</span><span className="text-[13px] text-[var(--k-muted)]">2 min</span></> },
    { title: "Link the ledger", time: "5 min", body: "Xero, QuickBooks or NetSuite, both ways.", artefact: <><span className="text-sm">Xero linked · 418 open invoices</span><span className="text-[13px] text-[var(--k-muted)]">5 min</span></> },
    { title: "Review exceptions", time: "overnight", body: "Halden matches overnight; you review what's left.", artefact: <><span className="text-sm">412 matched · 6 for review</span><span className="text-[13px] text-[var(--k-muted)]">next morning</span></> },
  ] };

export function StepsBlockDemo() {
  return <Frame><StepsBlock {...steps} /></Frame>;
}

API reference #

StepsBlock

component
PropTypeDefault
eyebrowstring—
title *string—
leadstring—
steps *readonly BlockStep[]—
footnotestring—
layout"row" | "scroll""row"
classNamestring—

Accessibility #

It is built on native elements and keeps aria-hidden, aria-current and aria-live 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.