Progress Indicator
Communicates a user's progress through a sequence of steps
View MarkdownOverview
The Progress Indicator communicates a user’s position within a multi-step process such as policy or indicator creation. It renders a sequence of steps along a track, with the current step highlighted and each step’s state conveyed through a status icon.
It is composed of two components: ProgressIndicator (the parent that draws the track and arranges the steps) and ProgressIndicatorStep (each individual step). The parent takes a currentIndex and positions the track’s filled segment over that step; each step derives its own active state by comparing its index to it.
Progress Indicator should not be used with fewer than three steps.
Usage
Import the components:
import { ProgressIndicator, ProgressIndicatorStep } from "@eqtylab/equality";
Basic usage with required properties:
<ProgressIndicator aria-label="Account setup progress" currentIndex={1}>
<ProgressIndicatorStep name="Account" status="success" />
<ProgressIndicatorStep name="Verification" status="editing" />
<ProgressIndicatorStep name="Confirm" status="neutral" />
</ProgressIndicator>
Variants
Horizontal (default)
The default layout arranges steps in a row. The example below mixes every status so each icon is visible. The step at currentIndex (Verification) is marked with aria-current="step" and the track fills its segment.
<ProgressIndicator aria-label="Progress Indicator" currentIndex={2}>
<ProgressIndicatorStep
name="Success"
description="Completed"
status="success"
/>
<ProgressIndicatorStep
name="Danger"
description="Action required"
status="danger"
/>
<ProgressIndicatorStep
name="Editing"
description="In progress"
status="editing"
/>
<ProgressIndicatorStep name="Info" description="Optional" status="info" />
<ProgressIndicatorStep name="Neutral" status="neutral" />
<ProgressIndicatorStep name="Empty" status="empty" />
</ProgressIndicator>
Vertical
Set layout="vertical" to stack the steps. The track and fill re-orient automatically.
<ProgressIndicator
layout="vertical"
currentIndex={2}
aria-label="Progress Indicator"
>
<ProgressIndicatorStep
name="Success"
description="Completed"
status="success"
/>
{/* …remaining steps… */}
</ProgressIndicator>
Interactive (onClick)
When a step is given an onClick handler it renders as a <button>, making it focusable and keyboard-operable.
const [active, setActive] = useState(1);
<ProgressIndicator aria-label="Policy creation steps" currentIndex={active}>
{steps.map((name, index) => (
<ProgressIndicatorStep
key={name}
name={name}
status={
index < active ? "success" : index === active ? "editing" : "neutral"
}
onClick={() => setActive(index)}
/>
))}
</ProgressIndicator>;
Link (href)
When a step is given an href it renders as an <a>.
<ProgressIndicator aria-label="Documentation progress" currentIndex={1}>
<ProgressIndicatorStep
name="Introduction"
status="success"
href="#introduction"
/>
<ProgressIndicatorStep
name="Installation"
status="editing"
href="#installation"
/>
<ProgressIndicatorStep name="Usage" status="neutral" href="#usage" />
</ProgressIndicator>
If a step has neither href nor onClick, it renders as a non-interactive <div> that is not focusable.
Props
ProgressIndicator
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
layout | Orientation of the steps | horizontal, vertical | horizontal | ❌ |
currentIndex | Array index of the current (active) step | number | 0 | ✅ |
elevation | Elevation applied to each step’s marker icon | sunken, base, raised, overlay | raised | ❌ |
aria-label | Accessible label for the step list | string | "Progress" | ❌ |
children | One or more ProgressIndicatorStep components | ReactNode | — | ✅ |
ProgressIndicatorStep
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
name | The step label | string | — | ✅ |
description | Secondary text shown beneath the name | string | — | ❌ |
status | Controls the step’s icon and colour | editing, empty, neutral, success, info, danger | neutral | ❌ |
href | Renders the step as an <a> | string | — | ❌ |
onClick | Renders the step as a <button> | (e: MouseEvent) => void | — | ❌ |