Skip to main content
Urbicon UI

Stepper

Multi-step progress indicator with horizontal/vertical layout, clickable navigation, and per-step state overrides.

Playground

  1. Account Create your account
  2. 2
    Profile Set up your profile
  3. 3
    Review Review and submit
Orientation
Variant
Size
Tier
<Stepper>
  <StepperStep label="Account" description="Create your account" />
  <StepperStep label="Profile" description="Set up your profile" />
  <StepperStep label="Review" description="Review and submit" />
</Stepper>

01 Examples

Checkout wizard

Bound activeStep with Back/Next navigation — the canonical multi-step form pattern.
Active step: 1 / 4
  1. 1
    Account Create account
  2. 2
    Profile Your details
  3. 3
    Preferences Customize Optional
  4. 4
    Done All set
<div class="flex w-full flex-col gap-4">
  <div class="flex items-center gap-2">
    <span class="text-text-tertiary text-xs font-medium">Active step:</span>
    <Badge size="xs" intent="primary" variant="soft">{interactiveStep + 1} / 4</Badge>
  </div>
  <Stepper bind:activeStep={interactiveStep} clickable>
    <StepperStep label="Account" description="Create account" />
    <StepperStep label="Profile" description="Your details" />
    <StepperStep label="Preferences" description="Customize" optional />
    <StepperStep label="Done" description="All set" />
  </Stepper>
  <div class="flex gap-2">
    <Button
      size="sm"
      variant="outlined"
      disabled={interactiveStep === 0}
      onclick={() => (interactiveStep = Math.max(0, interactiveStep - 1))}
    >
      Back
    </Button>
    <Button
      size="sm"
      disabled={interactiveStep === 3}
      onclick={() => (interactiveStep = Math.min(3, interactiveStep + 1))}
    >
      Next
    </Button>
  </div>
</div>

Mixed per-step states

Override auto-derived states with error or warning for individual steps — e.g. a checkout where payment failed but shipping needs review.
  1. Account Completed
  2. Payment Card declined
  3. Shipping Verify address
  4. 4
    Review Final check
<Stepper activeStep={2}>
  <StepperStep label="Account" description="Completed" />
  <StepperStep label="Payment" description="Card declined" state="error" />
  <StepperStep label="Shipping" description="Verify address" state="warning" />
  <StepperStep label="Review" description="Final check" />
</Stepper>

Optional steps in onboarding

Mark non-required steps with the optional flag — users see an 'Optional' hint and can skip them.
  1. Account Required
  2. 2
    Avatar Upload photo Optional
  3. 3
    Bio Tell us about you Optional
  4. 4
    Finish Complete setup
<Stepper activeStep={1}>
  <StepperStep label="Account" description="Required" />
  <StepperStep label="Avatar" description="Upload photo" optional />
  <StepperStep label="Bio" description="Tell us about you" optional />
  <StepperStep label="Finish" description="Complete setup" />
</Stepper>

02 Vertical Stepper

Vertical with content per step

Vertical orientation exposes a content slot per step — useful for inline instructions or embedded forms.
  1. Create Account Enter your email and password

    Enter your credentials to create a new account. We'll send a verification email to confirm your address.

  2. 2
    Personal Info Tell us about yourself

    Fill in your name, date of birth, and contact information. This helps us personalize your experience.

  3. 3
    Preferences Customize your experience Optional

    Choose your notification preferences, language, and theme settings.

  4. 4
    Complete Review and finish
<Stepper activeStep={1} orientation="vertical">
  <StepperStep label="Create Account" description="Enter your email and password">
    <div class="bg-surface-elevated border-border-subtle rounded-contain border p-4">
      <p class="text-text-secondary text-sm">
        Enter your credentials to create a new account. We'll send a verification email to
        confirm your address.
      </p>
    </div>
  </StepperStep>
  <StepperStep label="Personal Info" description="Tell us about yourself">
    <div class="bg-surface-elevated border-border-subtle rounded-contain border p-4">
      <p class="text-text-secondary text-sm">
        Fill in your name, date of birth, and contact information. This helps us personalize
        your experience.
      </p>
    </div>
  </StepperStep>
  <StepperStep label="Preferences" description="Customize your experience" optional>
    <div class="bg-surface-elevated border-border-subtle rounded-contain border p-4">
      <p class="text-text-secondary text-sm">
        Choose your notification preferences, language, and theme settings.
      </p>
    </div>
  </StepperStep>
  <StepperStep label="Complete" description="Review and finish" />
</Stepper>

Vertical with error state

A failed step blocks progress until resolved — surface the error inline via the step content slot.
  1. Account Created Email verified
  2. Payment Failed Card was declined

    Your card ending in •••• 4242 was declined. Please update your payment method.

  3. 3
    Ship Order Awaiting payment
<Stepper activeStep={2} orientation="vertical">
  <StepperStep label="Account Created" description="Email verified" />
  <StepperStep label="Payment Failed" description="Card was declined" state="error">
    <div class="border-danger/20 bg-danger/5 rounded-contain border p-4">
      <p class="text-danger text-sm font-medium">
        Your card ending in •••• 4242 was declined. Please update your payment method.
      </p>
    </div>
  </StepperStep>
  <StepperStep label="Ship Order" description="Awaiting payment" />
</Stepper>

03 Customization

slotClasses Override

Restyle individual slots — indicator color, label styling, separator thickness.
  1. Draft Write content
  2. 2
    Review Get feedback
  3. 3
    Publish Go live
<Stepper
  activeStep={1}
  slotClasses={{
    separator: 'h-1 rounded-none'
  }}
>
  <StepperStep label="Draft" description="Write content" />
  <StepperStep label="Review" description="Get feedback" />
  <StepperStep label="Publish" description="Go live" />
</Stepper>

Dark Glassmorphism

Fully custom frosted-glass stepper with unstyled mode.
  1. Design
  2. 2
    Develop
  3. 3
    Deploy
<Stepper
  unstyled
  activeStep={1}
  class="flex w-full items-center [&>li:last-child_[data-stepper-separator]]:hidden"
>
  <StepperStep
    unstyled
    label="Design"
    slotClasses={{
      stepItem: 'flex items-center [&:not(:last-child)]:flex-1',
      step: 'flex items-center gap-2.5 shrink-0',
      indicator:
        'flex size-9 items-center justify-center rounded-full text-sm font-semibold bg-white/25 text-white backdrop-blur-md border-2 border-white/30',
      label: 'text-sm font-medium text-white/90',
      separator: 'h-0.5 flex-1 mx-3 bg-white/20 rounded-full'
    }}
  />
  <StepperStep
    unstyled
    label="Develop"
    slotClasses={{
      stepItem: 'flex items-center [&:not(:last-child)]:flex-1',
      step: 'flex items-center gap-2.5 shrink-0',
      indicator:
        'flex size-9 items-center justify-center rounded-full text-sm font-semibold bg-white/40 text-white backdrop-blur-md border-2 border-white/50 shadow-lg shadow-white/10',
      label: 'text-sm font-semibold text-white',
      separator: 'h-0.5 flex-1 mx-3 bg-white/20 rounded-full'
    }}
  />
  <StepperStep
    unstyled
    label="Deploy"
    slotClasses={{
      stepItem: 'flex items-center',
      step: 'flex items-center gap-2.5 shrink-0',
      indicator:
        'flex size-9 items-center justify-center rounded-full text-sm font-semibold bg-white/10 text-white/50 backdrop-blur-md border-2 border-white/15',
      label: 'text-sm font-medium text-white/50',
      separator: 'hidden'
    }}
  />
</Stepper>

Terminal Progress

Monospace hacker aesthetic.
  1. BUILD
  2. TEST
  3. 3
    DEPLOY
  4. 4
    MONITOR
<Stepper
  unstyled
  activeStep={2}
  class="flex w-full items-center font-mono [&>li:last-child_[data-stepper-separator]]:hidden"
>
  <StepperStep
    unstyled
    label="BUILD"
    slotClasses={{
      stepItem: 'flex items-center [&:not(:last-child)]:flex-1',
      step: 'flex items-center gap-2 shrink-0',
      indicator:
        'flex size-7 items-center justify-center rounded text-xs font-bold bg-emerald-500/20 text-emerald-400 border border-emerald-500/30',
      label: 'text-xs text-emerald-300 tracking-wider',
      separator: 'h-px flex-1 mx-3 bg-emerald-500/20'
    }}
  />
  <StepperStep
    unstyled
    label="TEST"
    slotClasses={{
      stepItem: 'flex items-center [&:not(:last-child)]:flex-1',
      step: 'flex items-center gap-2 shrink-0',
      indicator:
        'flex size-7 items-center justify-center rounded text-xs font-bold bg-emerald-500/20 text-emerald-400 border border-emerald-500/30',
      label: 'text-xs text-emerald-300 tracking-wider',
      separator: 'h-px flex-1 mx-3 bg-emerald-500/20'
    }}
  />
  <StepperStep
    unstyled
    label="DEPLOY"
    slotClasses={{
      stepItem: 'flex items-center [&:not(:last-child)]:flex-1',
      step: 'flex items-center gap-2 shrink-0',
      indicator:
        'flex size-7 items-center justify-center rounded text-xs font-bold bg-emerald-500 text-neutral-950 border border-emerald-400 shadow-[0_0_12px_rgba(52,211,153,0.3)]',
      label: 'text-xs text-emerald-300 tracking-wider font-bold',
      separator: 'h-px flex-1 mx-3 bg-emerald-500/20'
    }}
  />
  <StepperStep
    unstyled
    label="MONITOR"
    slotClasses={{
      stepItem: 'flex items-center',
      step: 'flex items-center gap-2 shrink-0',
      indicator:
        'flex size-7 items-center justify-center rounded text-xs font-bold bg-transparent text-neutral-400 border border-neutral-600',
      label: 'text-xs text-neutral-400 tracking-wider',
      separator: 'hidden'
    }}
  />
</Stepper>

Wizard chrome like the glass or terminal looks above belongs in BlocksProvider presets — presets.Stepper for the shell, presets.StepperStep for the per-step slots — applied via preset. See Customization.

04 Accessibility

Built-in ARIA

The stepper renders as an <ol> with aria-label="Progress". The active step is marked with aria-current="step". Clickable steps get role="button" for screen reader identification. The data-orientation attribute exposes the layout direction.

Keyboard Navigation

Tab moves focus between clickable steps. Enter / Space activates the focused step. Focus rings use focus-visible: for keyboard-only visibility.

Step States

Completed, error, and warning steps use distinct icons (checkmark, X, warning triangle) in addition to color, ensuring status is never conveyed by color alone. Disabled steps are removed from the tab order via pointer-events-none and visual opacity-50.

Reduced Motion

All transitions use design token durations (--blocks-duration-fast, --blocks-duration-normal) which are reduced automatically when prefers-reduced-motion is active.

05 API Reference

17 props
17 props 1 required
Prop
Type
Default
Description

06 Types

Local type definitions used by this component.

6 types
Name
Kind
Category
Used by
Description

07 Installation

Import

import { Stepper, StepperStep } from '@urbicon-ui/blocks';