Ship-It Designv0.0.20

GitHub

WizardDialog

Modal multi-step flow built on Dialog + Stepper + Next/Back navigation driven by a steps array. Each step's content can be a node or a render function receiving the wizard context — useful for steps that need to disable Next from inside, or jump back imperatively.

The data shape#

tsx
<WizardDialog
  open={open}
  onOpenChange={setOpen}
  title="Add a connector"
  steps={[
    { id: 'name', label: 'Name', content: <NameForm />, canAdvance: () => name.length > 0 },
    { id: 'configure', label: 'Configure', content: ({ goBack }) => <Configure onBack={goBack} /> },
    { id: 'review', label: 'Review', content: <Summary /> },
  ]}
  onComplete={() => setOpen(false)}
/>

steps is rendered in order; the Stepper at the top tracks progress; the footer shows Back / Next / (last step) Done buttons.

Default#

Three-step "add connector" flow. The Next button is gated per step via canAdvance; the last step's Next becomes Done and fires onComplete, where the consumer typically closes the dialog.

Loading…

Step (WizardStep)#

  • id: string (required) — stable id. Used as the React key and the Stepper item id.
  • label: string (required) — visible label in the Stepper.
  • content: ReactNode | ((ctx: WizardContext) => ReactNode) (required) — the step body. Pass a node for static content or a function for content that needs the wizard context.
  • canAdvance?: (ctx: WizardContext) => boolean — predicate that gates the Next button for this step. Default: always true.

Wizard context (WizardContext)#

Passed to render-function content and canAdvance callbacks.

  • current: number — current step index (0-based).
  • total: number — total step count.
  • goNext: () => void — advance to the next step. Calling on the last step fires onComplete instead.
  • goBack: () => void — return to the previous step. No-op on the first step.
  • goTo: (index: number) => void — jump to an arbitrary step index. Useful for "Edit values" buttons inside a review step.
  • isFirst: boolean — convenience flag for current === 0.
  • isLast: boolean — convenience flag for the final step.

Step gating#

Returning false from canAdvance disables the Next button without disabling the step itself — users can still type into the field, edit the form, etc.

tsx
const steps = [
  {
    id: 'name',
    label: 'Name',
    content: <Input value={name} onChange={} />,
    canAdvance: () => name.trim().length > 0,
  },
];

Render-function content#

Pass a function as content to access the wizard context from inside the step body — for things like a Review step that lets the user jump back to a specific earlier step.

tsx
{
  id: 'review',
  label: 'Review',
  content: ({ goBack, goTo }) => (
    <>
      <Summary />
      <Button variant="ghost" onClick={() => goTo(0)}>Edit name</Button>
      <Button variant="ghost" onClick={goBack}>Back</Button>
    </>
  ),
}

Top-level props#

Props for WizardDialog
PropTypeDefaultDescription
openboolean | undefinedControlled open state.
defaultOpenboolean | undefinedUncontrolled initial open state.
onOpenChange((open: boolean) => void) | undefinedFires when the dialog open state changes.
steps *readonly WizardStep[]Ordered list of wizard steps.
initialStepnumber | undefined0Step index to start at. Default 0.
onComplete(() => void) | undefinedFires when Next is clicked on the last step. The consumer typically closes the dialog here.
titleReactNodeDialog title (visible heading).
descriptionReactNodeDialog description (rendered below the title for assistive tech).
widthstring | number | undefined560Pixel max-width of the dialog panel. Default 560.
nextLabelReactNodeNextOverride the Next button label. Default `'Next'`.
completeLabelReactNodeDoneOverride the Next button label on the last step. Default `'Done'`.
backLabelReactNodeBackOverride the Back button label. Default `'Back'`.
cancelLabelReactNodeOptional cancel slot rendered in the footer alongside the navigation.
onCancel(() => void) | undefinedFires when the cancel button is pressed. The consumer typically closes the dialog.