Stepper
Stepper is a progress indicator component used to display and navigate through a sequence of steps in a linear flow, such as forms, onboarding, or multi-step processes.
Usage
Basic usage
import { Stepper } from '@nofinite/nui';
<Stepper steps={['Info', 'Address', 'Payment']} active={1} />;
With step interaction
<Stepper
steps={['Start', 'Build', 'Finish']}
active={currentStep}
onChange={setCurrentStep}
/>
Variants
Stepper does not expose visual variants via props.
Styling and theming are handled through CSS variables and class names.
Guidelines:
- Use theming tokens (
--color-primary,--color-border, etc.) to adapt appearance. - Keep step labels short for best readability.
Sizes
The component has a single default size.
Customization tip: Sizes can be adjusted via CSS by overriding:
.ui-stepper-circle.ui-stepper-label.ui-stepper-line
States
The Stepper automatically manages visual states based on the active index.
<Stepper steps={['One', 'Two', 'Three']} active={1} />
States explained:
-
Active (
index === active) Highlighted circle and label, usesaria-current="step". -
Completed (
index < active) Displays a ✓ checkmark; connector line becomes active color. -
Upcoming (
index > active) Default muted appearance.
Native Props / Composition
The component renders a semantic navigation structure and supports composition through props.
<Stepper
steps={['Account', 'Verify', 'Complete']}
active={0}
onChange={(index) => console.log(index)}
className="my-custom-stepper"
/>
- Root element:
<nav> - Steps are rendered as
<button>elements for accessibility. classNameis forwarded to the root container.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | (string | StepItem)[] | — | List of steps to display |
active | number | — | Zero-based index of the active step |
onChange | (index: number) => void | — | Callback when a step is clicked |
className | string | "" | Additional class names for the root |
StepItem
interface StepItem {
label: React.ReactNode;
}
Allows rendering custom labels (icons, formatted text, etc.).
Behavior Notes
- Navigation is linear by default, but users can click any step if
onChangeis provided. - Completed steps automatically show a checkmark.
- The component is fully controlled via the
activeprop.
Example:
<Stepper steps={steps} active={2} />
Accessibility
- Renders inside a
<nav aria-label="Progress Steps">. - Steps are interactive
<button>elements. - Active step uses
aria-current="step". - Fully keyboard accessible (Tab + Enter/Space).
Recommended usage:
<Stepper steps={['Info', 'Confirm', 'Done']} active={1} />
Layout
- Takes full width of its container by default.
- Steps are laid out horizontally using flexbox.
- Connector lines automatically expand between steps.
<Stepper
steps={['Start', 'Middle', 'End']}
active={0}
style={{ maxWidth: 600 }}
/>
Best Practices
Do
- Use for linear, ordered flows.
- Keep step labels concise.
- Control state externally via
active.
Don’t
- Use for non-sequential navigation.
- Overload labels with long text.
- Rely on it as the sole indicator of form validation.