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.json

Usage

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 upcoming and current it shows stepNumber; in done it swaps to a check icon on a filled accent fill.
  • Title — serif at 1.125rem with text-wrap: balance. An sr-only "Step N: " prefix keeps the step number in the screen-reader path.
  • Bodychildren. Wraps with [text-wrap:pretty].
  • Metadata row — optional duration (tabular-nums) and a tone-coded effort badge.

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

  • easycb-success
  • mediumcb-warning
  • hardcb-error

Color is paired with the literal label ("Easy" / "Medium" / "Hard") so the cue is never color-only.

Props

PropTypeDefaultDescription
stepNumbernumberrequired1-indexed step number — rendered in the badge for upcoming and current.
titleReactNoderequiredStep heading. Serif.
childrenReactNodeStep body.
state'upcoming' | 'current' | 'done''current'Visual state.
durationstringTime estimate label (e.g. '~10 min').
effort'easy' | 'medium' | 'hard'Tone-coded effort badge in the metadata row.
classNamestringMerged 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 supply role="list"/role="listitem") when the order is semantic.
  • The badge is aria-hidden="true"; an sr-only "Step N: " prefix on the title keeps the step number in the screen-reader path.
  • Decorative separators (the · between duration and effort) are aria-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 flat stepNumber / title / children / state / duration / effort API, replaces hardcoded var(--color-*) tokens with --cb-* semantic tokens, and adds a tone-coded effort badge in place of the per-step "tip" callout.