Stepper
A progress indicator that walks the user through a sequence of ordered steps with pending, active, complete, and error states.
Renders an ordered list; the active step receives aria-current="step"; interactive mode exposes each step as a labelled button.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Stepper currentStep={1}>
<Step title="Account" />
<Step title="Profile" />
<Step title="Confirm" />
</Stepper>
);
}
import { Stepper, Step } from "@arshad-shah/cynosure-react";
<Stepper currentStep={1}> <Step title="Account" /> <Step title="Profile" /> <Step title="Confirm" /></Stepper>currentStep is zero-indexed. Steps before currentStep derive status="complete", the matching step is "active", and any later steps are "pending". Pass status explicitly to override the default for a specific step (handy for "error").
Variants
Section titled “Variants”Vertical orientation
Section titled “Vertical orientation”Use orientation="vertical" for sidebar-style flows.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Stepper currentStep={1} orientation="vertical">
<Step title="Account" description="Email and password" />
<Step title="Profile" description="Name and avatar" />
<Step title="Confirm" description="Review and finish" />
</Stepper>
);
}
Variants — dots, lines, icons
Section titled “Variants — dots, lines, icons”Switch the marker style with variant="numbered" (default), "dots", "lines", or "icons". The icons variant accepts a custom icon on each Step.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
const IconCart = () => (
<svg
aria-hidden="true"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="9" cy="21" r="1" />
<circle cx="20" cy="21" r="1" />
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" />
</svg>
);
const IconCard = () => (
<svg
aria-hidden="true"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<rect x="1" y="4" width="22" height="16" rx="2" ry="2" />
<line x1="1" y1="10" x2="23" y2="10" />
</svg>
);
const IconCheck = () => (
<svg
aria-hidden="true"
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<polyline points="20 6 9 17 4 12" />
</svg>
);
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<Stepper currentStep={1} variant="numbered">
<Step title="Cart" />
<Step title="Payment" />
<Step title="Confirm" />
</Stepper>
<Stepper currentStep={1} variant="dots">
<Step title="Cart" />
<Step title="Payment" />
<Step title="Confirm" />
</Stepper>
<Stepper currentStep={1} variant="lines">
<Step title="Cart" />
<Step title="Payment" />
<Step title="Confirm" />
</Stepper>
<Stepper currentStep={1} variant="icons">
<Step title="Cart" icon={<IconCart />} />
<Step title="Payment" icon={<IconCard />} />
<Step title="Confirm" icon={<IconCheck />} />
</Stepper>
</div>
);
}
Use size="sm", "md" (default), or "lg" to scale the marker and typography.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<Stepper currentStep={1} size="sm">
<Step title="Plan" />
<Step title="Build" />
<Step title="Ship" />
</Stepper>
<Stepper currentStep={1} size="md">
<Step title="Plan" />
<Step title="Build" />
<Step title="Ship" />
</Stepper>
<Stepper currentStep={1} size="lg">
<Step title="Plan" />
<Step title="Build" />
<Step title="Ship" />
</Stepper>
</div>
);
}
Step descriptions
Section titled “Step descriptions”Pass description to render a muted second line under the title.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Stepper currentStep={1}>
<Step title="Account" description="Email and password" />
<Step title="Profile" description="Name, avatar, and bio" />
<Step title="Confirm" description="Review and finish" />
</Stepper>
);
}
Interactive (clickable steps)
Section titled “Interactive (clickable steps)”Pass interactive together with onStepChange to let users click completed or active steps to jump back. Pending steps remain unreachable.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [step, setStep] = useState(2);
return (
<Stepper currentStep={step} interactive onStepChange={setStep}>
<Step title="Account" />
<Step title="Profile" />
<Step title="Confirm" />
<Step title="Done" />
</Stepper>
);
}
Error state
Section titled “Error state”Force a step’s status with the status prop — typically "error" for validation failures.
import { Step, Stepper } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Stepper currentStep={1}>
<Step title="Account" />
<Step title="Profile" status="error" description="Avatar upload failed" />
<Step title="Confirm" />
</Stepper>
);
}
Accessibility
Section titled “Accessibility”- The root renders as
<ol>so the order of steps is exposed to assistive tech. - The active step’s
<li>carriesaria-current="step". - Each step also gets a
data-status="pending|active|complete|error"attribute so consumers can target individual states with CSS. - In
interactivemode each reachable step renders a real<button>with anaria-labelderived from its title (or"Step N"if the title is non-string). - Connector lines are
aria-hidden="true"— purely decorative.
Recipes
Section titled “Recipes”- Use
variant="dots"for compact progress meters where titles aren’t useful. - Pair with a form’s
isValidflag to advancecurrentSteponly when the current step’s fields pass validation. - Provide a custom
iconon eachStepplusvariant="icons"for onboarding flows where the steps represent distinct activities. - Combine
interactivewith controlledcurrentStepto let users freely navigate between visited steps.