Theme studio

Design a theme, preview it live, then export it. Saved in this browser.

Quick picks #10b981
Generated scale
50100200300400500600700800900
Some text is below AA

Multi-step flows

Split long tasks into named steps, show where people are, and let them go back without losing anything.

  1. DatesDone
  2. ApproverIn progress
  3. ReviewUp next

The problem

A 30-field form is overwhelming, but a wizard that hides how many steps are left, or loses answers on Back, is worse. People abandon flows when they can't tell how close they are to done.

When to use it

Use it for

  • Tasks with distinct phases: onboarding, leave requests with documents, checkout.
  • Later steps depend on earlier answers.

Not for

  • Short forms that fit on one screen: splitting them adds clicks.
  • Settings people edit in any order: use tabs or sections.

Anatomy

  1. StepperNamed steps with status: complete, current, upcoming or error.
  2. ProgressProgressSteps for “Step 2 of 5” where names don't fit, like on phones.
  3. Step contentOne topic per step, with its own heading.
  4. NavigationBack and Continue at the bottom; the final button names the outcome: “Submit request”.

How to build it

  1. Group fields into three to six steps with short names.
  2. Show the Stepper above the content; use ProgressSteps on narrow screens.
  3. Validate each step on Continue, and mark a step as error if it needs attention.
  4. Keep all answers in one state object so Back never loses anything.
  5. Move focus to the new step's heading after each change.
  6. End with a review step before anything is submitted.
app.tsx
import { Button, Stepper } from "@nexera-ui/react";

const STEPS = [
  { label: "Dates" },
  { label: "Approver" },
  { label: "Documents" },
  { label: "Review" },
];

<Stepper aria-label="Leave request" steps={STEPS} current={step} />
<StepContent step={step} values={values} onChange={setValues} />
<div className="flex justify-between">
  <Button variant="secondary" isDisabled={step === 1} onPress={() => setStep(step - 1)}>
    Back
  </Button>
  <Button onPress={() => setStep(step + 1)}>
    {step === STEPS.length ? "Submit request" : "Continue"}
  </Button>
</div>

Accessibility

  • The current step has aria-current="step"; completed and error steps say so in text.
  • ProgressSteps can announce changes, so screen reader users hear “Step 3 of 4”.
  • Focus moves to the new step's heading, not to the top of the page.

Do and don't

DoName every step and show how many are left.

Don'tShow “Next” with no idea how far there is to go.

DoKeep answers when going back.

Don'tClear later steps whenever an earlier one changes.

DoName the final button after the outcome: “Submit request”.

Don'tEnd with a generic “Finish”.