Numbered Stepper
A free numbered stepper component for React and Next.js.
Brief
Agree the outcome and constraints.
completedPrototype
Test the riskiest interaction.
currentReview
Check evidence with the team.
upcomingRelease
Ship progressively and observe.
upcoming
Customise
Code
<TimelineStepper
steps={[
{ id: "brief", label: "Brief", description: "Agree the outcome and constraints." },
{ id: "prototype", label: "Prototype", description: "Test the riskiest interaction." },
{ id: "review", label: "Review", description: "Check evidence with the team." },
{ id: "release", label: "Release", description: "Ship progressively and observe." },
]}
label="Launch progress"
current={1}
/>Numbered Stepper is a free React stepper component for Next.js, styled with Tailwind and animated with Motion. It maps a controlled active index onto completed, current and upcoming steps, then fills the connector to the active stop while keeping every text state explicit.
The same component supports horizontal and vertical layouts without changing its ordered-list semantics. Forward updates pulse only the newly active stop, backward updates settle without a pulse, and reduced-motion visitors receive every connector, number and check state instantly.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/timeline-stepperUsage
"use client";
import { useState } from "react";
import { TimelineStepper } from "@/components/timeline-stepper";
const steps = [
{ id: "brief", label: "Brief", description: "Agree the outcome." },
{ id: "prototype", label: "Prototype", description: "Test the risk." },
{ id: "review", label: "Review", description: "Check the evidence." },
{ id: "release", label: "Release", description: "Ship and observe." },
];
export default function Page() {
const [current, setCurrent] = useState(1);
return (
<>
<TimelineStepper
steps={steps}
current={current}
label="Launch progress"
/>
<button
type="button"
onClick={() => setCurrent((step) => Math.min(step + 1, steps.length - 1))}
>
Next step
</button>
</>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| steps | { id: string; label: string; description?: string }[] | required | Three to five steps in display order. Each id is the stable React key used to preserve identity when the list reorders. |
| current | number | required | Controlled zero-based active index. Lower and upper out-of-range values are clamped to the available steps. |
| orientation | "horizontal" | "vertical" | "horizontal" | Sets the visual and connector orientation. |
| label | string | "Progress" | Accessible name applied to the ordered list. |
| className | string | undefined | Additional classes merged onto the wrapper. |
Customisation
Numbered Stepper deliberately adds no component-specific colour tokens. Its connector, stops, text and focus treatment inherit the shared primary, primary-foreground, border, foreground, muted and ring semantic tokens, so a theme change updates the whole stepper without editing its source.
.launch-stepper {
--primary: var(--color-brand-600);
--ring: var(--color-accent-400);
}
<TimelineStepper
className="launch-stepper"
steps={steps}
current={current}
orientation="vertical"
/>Frequently asked questions
- Is Numbered Stepper free for commercial use?
- Yes. Numbered Stepper is MIT licensed, so you can use it in personal and commercial projects without attribution.
- How does the stepper support accessibility and reduced motion?
- It renders a labelled ordered list, applies aria-current only to the active step and includes an explicit completed, current or upcoming text state for every item. With reduced motion enabled, the connector, check and state changes update instantly without springs, pulses or path drawing.
- Can I use a vertical layout or change its colours?
- Set orientation to vertical for a vertical connector and item layout. Colours inherit the library semantic tokens, so changing primary, border, foreground, muted or ring in your theme retints the component consistently.