Step Card
A full content card representing a single step in a multi-step process — onboarding flows, recipes, tutorials, guided setup. Larger and more prominent than a StepProgress dot or a StepTimeline row — StepCard is the surface the user actually reads while doing the step.
Step 2: Bloom the aromatics
Warm the oil over medium heat, then add the spices and stir until they smell like themselves — about a minute before the garlic goes in.
~3 minMedium
Customize
State
current
Effort
medium
Metadata
Installation
npx shadcn@latest add https://craftbits.dev/r/step-card.jsonUsage
import { StepCard } from "@craft-bits/core";
<StepCard stepNumber={2} title="Bloom the aromatics" duration="~3 min" effort="medium">
Warm the oil over medium heat, then add the spices and stir until they
smell like themselves — about a minute before the garlic goes in.
</StepCard>A vertical "done / current / upcoming" stack:
<>
<StepCard stepNumber={1} title="Mise en place" state="done" duration="~5 min" effort="easy">
Pull every ingredient onto the counter, measure into bowls, clear the workspace.
</StepCard>
<StepCard stepNumber={2} title="Bloom the aromatics" state="current" duration="~3 min" effort="medium">
Warm the oil, add the spices, stir until they smell like themselves.
</StepCard>
<StepCard stepNumber={3} title="Reduce and finish" state="upcoming" duration="~12 min" effort="hard">
Pour in the stock, drop to a simmer, let the sauce tighten.
</StepCard>
</>Anatomy
- Header row — numbered badge (top-left) paired with a serif title.
- Badge — 8×8 circle. In
upcomingandcurrentit showsstepNumber; indoneit swaps to a check icon on a filled accent fill. - Title — serif at 1.125rem with
text-wrap: balance. Ansr-only"Step N: "prefix keeps the step number in the screen-reader path. - Body —
children. Wraps with[text-wrap:pretty]. - Metadata row — optional
duration(tabular-nums) and a tone-codedeffortbadge.
States
- Upcoming — muted surface, dim badge, dim title. "Not yet."
- Current (default) — 3px accent left rail, accent-tinted badge, soft two-layer lift shadow. "Do this now."
- Done — muted surface, filled accent badge with a check icon (replaces the step number). "Finished."
Effort tones
- easy →
cb-success - medium →
cb-warning - hard →
cb-error
Color is paired with the literal label ("Easy" / "Medium" / "Hard") so the cue is never color-only.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
stepNumber | number | required | 1-indexed step number — rendered in the badge for upcoming and current. |
title | ReactNode | required | Step heading. Serif. |
children | ReactNode | — | Step body. |
state | 'upcoming' | 'current' | 'done' | 'current' | Visual state. |
duration | string | — | Time estimate label (e.g. '~10 min'). |
effort | 'easy' | 'medium' | 'hard' | — | Tone-coded effort badge in the metadata row. |
className | string | — | Merged onto the root <div> via cn(). |
The native HTML title attribute is replaced by the ReactNode title prop via Omit<HTMLAttributes<HTMLDivElement>, 'title'>.
Accessibility
- Renders as a plain
<div>. Wrap a stack in<ol>/<li>(or supplyrole="list"/role="listitem") when the order is semantic. - The badge is
aria-hidden="true"; ansr-only"Step N: "prefix on the title keeps the step number in the screen-reader path. - Decorative separators (the
·between duration and effort) arearia-hidden="true". - The effort badge text is the label itself — color is a redundant cue, not the only one.
- No motion — safe for users with
prefers-reduced-motion: reduce.
Credits
- Extracted from:
terminal-dreams(src/components/cookbook/StepCard.tsx). The original baked in a cookbook timer hook, sound effects, navigation buttons, and a progress bar driven by parent state. The library version is purely presentational: it drops the timer/sound/nav and exposes a flatstepNumber/title/children/state/duration/effortAPI, replaces hardcodedvar(--color-*)tokens with--cb-*semantic tokens, and adds a tone-codedeffortbadge in place of the per-step "tip" callout.