Stepper
Multi-step form (questionnaire, checkout, setup wizard). Steps stay mounted so values survive Back and submit together; Continue checks only the current step's native constraints, plus an optional async onNext guard with a spinner. Progress header with springing connectors; works with onSubmit or a Server Action.
import { Field } from "@/components/ui/field";import { Input } from "@/components/ui/input";import { Stepper, StepperFooter, StepperList, StepperStep,} from "@/components/ui/stepper";import { createBot } from "./actions"; // "use server"const steps = [ { value: "server", title: "Server", description: "Where the bot will live." }, { value: "bot", title: "Bot", description: "How members will see it." },];// Server page: steps are plain data and the form posts to a Server Action.export default function SetupPage() { return ( <Stepper steps={steps} action={createBot}> <StepperList /> <StepperStep value="server"> <Field label="Server ID" required> <Input name="serverId" pattern="[0-9]{17,20}" /> </Field> </StepperStep> <StepperStep value="bot"> <Field label="Display name" required> <Input name="botName" maxLength={32} /> </Field> </StepperStep> <StepperFooter submitLabel="Create bot" /> </Stepper> );}<Stepper>
Multi-step form. Every step stays mounted (hidden), so values survive Back and submit together; Continue checks only the current step's native constraints, and the last step submits the form (onSubmit, or a Server Action through action).
steps*StepInfo[]Steps in order:
value,titleand an optionaldescriptionfor the header.defaultValuestringStep shown at first render (uncontrolled).
onValueChange(value: string) => voidCalled with the new step's
value.valuestringCurrent step's
value. Controlled withonValueChange, or start atdefaultValue.
| Prop | Type | Default |
|---|---|---|
steps*Steps in order: | StepInfo[] | — |
defaultValueStep shown at first render (uncontrolled). | string | — |
onValueChangeCalled with the new step's | (value: string) => void | — |
valueCurrent step's | string | — |
Also accepts every <form> prop.
<StepperList>
Progress header. Finished steps are links back; the connector fills on a spring.
Also accepts every <ol> prop (none of its own).
<StepperStep>
One step's fields. Hidden, not unmounted, while inactive. onNext runs after its native constraints pass; return false (or resolve false) to stay, e.g. after a server check.
children*ReactNodeThe step's fields.
value*stringMatches a step in
steps.onNextGuardRuns on Continue after the native checks; return false to stay.
| Prop | Type | Default |
|---|---|---|
children*The step's fields. | ReactNode | — |
value*Matches a step in | string | — |
onNextRuns on Continue after the native checks; return false to stay. | Guard | — |
<StepperFooter>
Back and Continue; the last step's button submits. Continue shows a spinner while onNext runs.
backLabeldefault"Back"ReactNodeBack button text.
nextLabeldefault"Continue"ReactNodeContinue button text.
submitLabeldefault"Submit"ReactNodeSubmit button text on the last step.
| Prop | Type | Default |
|---|---|---|
backLabelBack button text. | ReactNode | "Back" |
nextLabelContinue button text. | ReactNode | "Continue" |
submitLabelSubmit button text on the last step. | ReactNode | "Submit" |
- type StepInfo
- { value: string; title: string; description?: string }
- type Guard
- () => boolean | undefined | Promise<boolean | undefined>
* required. Every component also takes className.