Zetta v1.6

Components · Wayfinding

Progress tracker

A read-only map of a multi-step flow — checkout, onboarding, a wizard. Completed steps fill Primary with a check, the current step rings Primary, upcoming steps stay neutral, and an errored step goes danger. The connectors fill in behind you.

Preview

Cart
Shipping
3
Payment
4
Review

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Progress tracker" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `progress-tracker` spec (variants: completed, current, upcoming, error) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `progress-tracker` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

See Navigation — Stepper for full state table. Progress Tracker uses the same stepper token set.

State Indicator Label
Upcoming {colors.surface-muted} {colors.muted}
Active {colors.primary} {colors.ink} bold
Completed {colors.primary} + check {colors.muted}
Error {colors.danger} + error icon {colors.danger}

When to use

  • Multi-step forms where the user needs to know how many steps exist and how far along they are.
  • Onboarding flows (3–7 steps).
  • Checkout or configuration wizards.

When not to use

  • Single-step forms — no tracker needed.
  • Flows with more than 7 steps — consider a sidebar stepper or breaking the flow into sections.
  • Read-only audit trail of actions taken — use a Timeline component pattern instead.
  • Tab navigation between sections — use Tabs.

Do

  • Show step labels in the full variant — users need to understand what each step is, not just its number.
  • Mark a step as error when the user returns to it and it has invalid data.
  • Always show the current step as the active node — never skip it.
  • Enable clicking on completed steps to go back — the node is the navigation control.

Don't

  • Don't show more than 7 steps in the full variant — truncate or restructure the flow.
  • Don't update the tracker while an async step operation is pending — wait for success before advancing.
  • Don't hide the tracker on mobile — reduce to the compact variant instead.
  • Step labels: noun phrase or gerund. "Account info", "Payment", "Review" — not "Step 1", "Step 2".
  • Max label length: 12 characters before truncation in the maxWidth: 80px constraint. Keep short.
  • Error label: same label text — the error state is communicated by the node icon, not the label.

Keyboard

Progress Tracker is non-interactive by default. When navigable={true}, completed steps are clickable — see Stepper for keyboard spec.

Key Behavior
Tab Moves focus to each completed-step node (clickable to navigate back)
Enter / Space Navigates back to the focused completed step

Accessibility

  • ARIA role: role="list" on the tracker container. Each step is role="listitem".
  • Current step: aria-current="step" on the current step node.
  • Completed steps: if clickable (back navigation), they are role="button" with aria-label describing the step name and state: "Step 2: Payment — completed, click to go back".
  • Upcoming steps: not interactive — aria-disabled="true" if rendered as buttons, or use a <span> instead.
  • Progress announcement: wrap the tracker in aria-label="Form progress: Step 2 of 4" on the container <nav> or <div role="navigation">.
  • Error step: aria-invalid="true" on the step and announce the error via a live region.

Spec

Values and token references resolved straight from the Zetta spec.

progress-tracker
display
flex
alignItems
flex-start
width
100%
gap
0
progress-tracker-step
display
flex
flexDirection
column
alignItems
center
flex
1
position
relative
progress-tracker-node
width
28px
height
28px
borderRadius
{rounded.full}
borderWidth
2px
borderStyle
solid
display
flex
alignItems
center
justifyContent
center
fontFamily
Geist
fontSize
13px
fontWeight
500
lineHeight
1
zIndex
1
position
relative
flexShrink
0
progress-tracker-node-completed
backgroundColor
{colors.primary}
borderColor
{colors.primary}
textColor
{colors.primary-text}
iconSize
14px
iconColor
{colors.primary-text}
progress-tracker-node-current
backgroundColor
{colors.canvas}
borderColor
{colors.primary}
textColor
{colors.primary}
progress-tracker-node-upcoming
backgroundColor
{colors.canvas}
borderColor
{colors.hairline}
textColor
{colors.muted}
progress-tracker-node-error
backgroundColor
{colors.danger-bg}
borderColor
{colors.danger}
textColor
{colors.danger}
iconSize
14px
iconColor
{colors.danger}
progress-tracker-connector
height
2px
flex
1
position
absolute
top
13px
left
calc(50% + 14px)
right
calc(-50% + 14px)
zIndex
0
progress-tracker-connector-completed
backgroundColor
{colors.primary}
progress-tracker-connector-upcoming
backgroundColor
{colors.hairline}
progress-tracker-label
fontFamily
Geist
fontSize
12px
fontWeight
400
textColor
{colors.muted}
marginTop
{spacing.xs}
textAlign
center
maxWidth
80px
overflow
hidden
textOverflow
ellipsis
whiteSpace
nowrap
progress-tracker-label-current
fontWeight
500
textColor
{colors.ink}
progress-tracker-label-completed
textColor
{colors.primary}
progress-tracker-label-error
textColor
{colors.danger}
progress-tracker-compact
display
flex
alignItems
center
gap
{spacing.xs}
progress-tracker-dot
width
8px
height
8px
borderRadius
{rounded.full}
progress-tracker-dot-completed
backgroundColor
{colors.primary}
progress-tracker-dot-current
backgroundColor
{colors.primary}
width
24px
borderRadius
{rounded.full}
progress-tracker-dot-upcoming
backgroundColor
{colors.hairline}
progress-tracker-vertical
flexDirection
column
alignItems
flex-start
gap
0
progress-tracker-vertical-step
flexDirection
row
alignItems
flex-start
gap
{spacing.sm}
flex
none
progress-tracker-vertical-connector
width
2px
flex
1
minHeight
24px
marginLeft
13px
backgroundColor
{colors.hairline}
progress-tracker-vertical-connector-completed
backgroundColor
{colors.primary}
progress-tracker-mobile
display
flex
alignItems
center
gap
{spacing.sm}
progress-tracker-mobile-label
fontFamily
Geist
fontSize
13px
fontWeight
500
textColor
{colors.ink}
progress-tracker-mobile-sublabel
fontFamily
Geist
fontSize
12px
fontWeight
400
textColor
{colors.muted}

Known gaps

  • Clickable completed-step back navigation interaction spec — confirmed deferred to runtime implementation; no token gaps remain.