Stepper
Shows where people are in a flow with a fixed order, such as a checkout or a sign-up, and how much is left. It is a numbered list, not navigation.
- AccountEmail and password
- CompanyTax ID and address
- ReviewCheck and activate
Installation
Set up Camaleo once (Installation), then import what you need. It is a client component: each step reads its status from the stepper.
import { Stepper, Step, StepIndicator, StepTitle, StepDescription, StepSeparator } from "@camaleo/react";Anatomy
A Stepper is an <ol> and each Step an <li>, so screen readers say "list, 4 items" and the position of each one. Set activeStep on the stepper and every step works out its status: done before it, current at it, upcoming after it. The line between steps is drawn by the step itself, or by a StepSeparator placed last in it; the indicator is hidden from screen readers, so the title carries the meaning. A horizontal stepper narrower than 30rem (a container query, not the viewport) hides every title but the current one.
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above.
- Cart
- Shipping
- Payment
- Review
- Cart
- Shipping
- Payment
- Review
Step 1 of 4Cart
Cerrado beans 500 g, paper filters and a stoneware mug. Subtotal $54.80.
Back and Continue
Press Continue. Focus moves to the new step's heading, so a screen reader says "Step 2 of 4: Shipping" and keyboard users start at the top of the new form.
- CartDone
- ShippingIn progress
- PaymentNot started
State in words
Color and a check mark are not enough. Name the list with aria-label and give each state a word, visible or in VisuallyHidden.
- Payment
- Review
Go back to a finished step
Click Cart. Only steps people already reached are links; steps ahead stay plain text, because their data doesn't exist yet.
- Cart
- Shipping
- PaymentCard declined
- Review
Card declined. Try another card.
A step with an error
status="error" turns the step red with a cross and keeps aria-current when it is the active step. Say what went wrong in words too, because color and the icon are not announced.
- Ordered
- Packed
- Delivered
One line styled apart
Place a StepSeparator last in a step when one line needs its own look, such as a dashed line to a step that waits on someone else.
- Store profileName, logo and address of Grão Coffee Co.
- Add products12 of 12 imported from your spreadsheet.
- Connect paymentsLink a bank account to receive sales.
- Open the storePick a domain and publish.
Vertical, with descriptions
A column has room for a line under each step. Use it in a sidebar or for a setup checklist people come back to.
- Create accountana@graocoffee.com
- Choose a planPro, $12/mo
- Invite your teamOptionalAdd people now or later in Settings.
- Start sellingYour dashboard is ready.
Optional step
Mark it with a badge, not just lighter text, so people know they can move on without it.
- Cart
- Shipping
- Payment
- Review
Compact on phones
Below 30rem of width, a horizontal stepper keeps only the current title on screen; the others stay in the list for screen readers. Add "Step 2 of 4" above it so people still see how long the flow is.
In context
These are whole pieces of UI you can copy, in the skin you picked.
- Cart
- Shipping
- Payment
- Review
Set up your store
2 of 4 done- Store profile
- Add products
- Connect payments
- Open the store
Sales go to this account every business day. It takes about 3 minutes.
- Ordered03/14, 9:12 AM
- Packed03/14, 4:40 PM
- Out for deliveryExpected today by 6 PM
- DeliveredSignature required
Guidelines
- Business
- Documents
- Shipping
- Launch
People read the whole flow at a glance and know how far they are from the end.
- Tell us about your business and its owners
- Upload your documents
- Configure shipping zones and rates
- Review and launch your store
They don't fit side by side, so the stepper hides all but the current one and people can't see what's ahead. Put the details in each step's heading.
Settings pages have no first or last section, and nothing is ever "done".
- Profile
- Notifications
- Billing
Numbers and check marks promise an order and an end that don't exist, and the steps can't be clicked.
Props
completed, the one at it is
current and the ones after it are upcoming, unless a Step sets its own status.Step takes status ("completed" · "current" · "upcoming" · "error"), or the shorthands completed and current; without them, the status comes from activeStep, and is "upcoming" when there is none. StepIndicator takes its step's status, or its own status; with "completed" it shows a check mark and with "error" a cross instead of its children. The rest are the native props of <ol>, <li> and <span>.
Styling hooks
Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the stepper itself.
Attributes
Tokens it reads
Color
Shape & size
Type & motion
This component only
/* square indicators and a thicker line in the checkout */
.checkout [data-slot="stepper"] {
--cml-step-indicator-radius: 6px;
--cml-stepper-line: 3px solid var(--cml-border-control);
}Accessibility
- It is an <ol>: screen readers announce the number of steps and the position of each one. Name it with aria-label.
- The current step has aria-current="step". Completed and upcoming steps are not announced by color or the check mark, which is aria-hidden: add a word such as "done" in VisuallyHidden. The same goes for an error: say what went wrong in the title or a StepDescription.
- When the step changes, move focus to the new step's heading, and put "Step 2 of 4" in it, so screen readers and keyboard users start in the right place.
- Make only reached steps clickable. Steps ahead stay text, so people never land on a form whose earlier answers are missing.