Skip to main content
Urbicon UI

Stepper

Multi-step progress indicator with clickable navigation.

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

Stepper is controlled by a 0-based activeStep (bind:activeStep for two-way). Each indicator shows its step number, a checkmark once the step is complete, or a status icon for an error or warning step. clickable lets users jump to a step (updating activeStep and firing onStepChange), and linear limits that to completed steps plus the next one.

Checkout wizard

Bind activeStep and drive it with Back/Next buttons.
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 the auto-derived state of individual steps with error or warning. For example, 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, and users see an 'Optional' hint below the description.
  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

Surface a failed step's cause inline via the step content slot. Gate progress with linear or your own navigation, because state=error is visual only.
  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

Nudge one slot while the rest keep their defaults. Here slotClasses thickens the separator into a square bar.
  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

Drop the tokens with unstyled and rebuild every slot through slotClasses, here into a frosted-glass stepper on a gradient.
  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>

Wizard chrome like the glass look 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 non-interactive (cursor-not-allowed, pointer-events-none) and never receive a tabindex or role, so they stay out of the tab order. They intentionally skip an opacity wash, which would drop the label below the WCAG AA contrast threshold. The muted indicator carries the disabled look.

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

18 props
18 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';