Menu

Change language

GitHub repo

Stepper

stepperui

Multi-step indicator — horizontal or vertical, with completed / current / upcoming states and optional descriptions per step. Use for onboarding wizards and checkout flows.

When to use which

Decision Guide

Timeline showcases chronological events and milestones past-to-present. Stepper guides users through a linear, multi-step workflow requiring active user progression.

ComponentRole
Timeline

Chronological feeds, delivery tracking logs, audit trails, and product roadmap milestones.

Activity & Milestone Stream
Steppercurrent

Multi-step wizards, checkout sequences, onboarding flows, and form completion tracking.

Workflow Progression
  • Activity logs, tracking events, & milestones → Timeline (view)
  • Multi-step wizard or form progression → Stepper

Installation

$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/stepper.json
Manifest:https://uipkge.dev/r/svelte/stepper.jsonInstalls to:src/lib/components/ui/stepper/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
status
'pending''active''completed''error'
pendingoptional
size
'sm''default''lg'
defaultoptional
stepsStepperStep[]—optional
value

Controlled active step (1-based). Bind with `bind:value`.

number—optional
orientationStepperOrientationhorizontaloptional
stepsSnippet

Override the header strip (defaults to the steps list).

Snippet—optional
childrenSnippet<[{ activeStep: number; steps: StepperStep[] }]>—optional
refHTMLDivElement | null—optional
onValueChange(value: number) => void—optional
onStepClick

Fires with the 1-based step index on every step click that navigates (alongside `onValueChange`).

(stepIndex: number) => void—optional

Schema

Type aliases from this item's source — use them to shape the data you pass in.

StepperContextValue
interface StepperContextValue {
  orientation: () => StepperOrientation
  size: () => StepperSize
  activeStep: () => number
  steps: () => StepperStep[]
  goToStep: (stepIndex: number) => void
  isClickable: (index: number) => boolean
  getStatus: (index: number) => StepperStatus
}
StepperStep
interface StepperStep {
  id: string | number
  title: string
  description?: string
  icon?: IconComponent
  disabled?: boolean
  error?: boolean
}

Used by

Files installed (12)

  • src/lib/components/ui/stepper/Stepper.svelte2.8 kB
    <script lang="ts" module>
      import type { Snippet } from 'svelte'
      import type { HTMLAttributes } from 'svelte/elements'
      import type { StepperOrientation, StepperSize } from './context'
      import type { StepperStep } from './types'
    
      // Omit children: ours takes render params, the base Snippet takes none.
      export interface StepperProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
        steps?: StepperStep[]
        /** Controlled active step (1-based). Bind with `bind:value`. */
        value?: number
        orientation?: StepperOrientation
        size?: StepperSize
        /** Override the header strip (defaults to the steps list). */
        stepsSnippet?: Snippet
        children?: Snippet<[{ activeStep: number; steps: StepperStep[] }]>
        ref?: HTMLDivElement | null
        onValueChange?: (value: number) => void
        /** Fires with the 1-based step index on every step click that navigates (alongside `onValueChange`). */
        onStepClick?: (stepIndex: number) => void
      }
    </script>
    
    <script lang="ts">
      import { cn } from '$lib/utils'
      import { setStepperContext, type StepperStatus } from './context'
      import StepperItem from './StepperItem.svelte'
    
      let {
        class: className,
        steps = [],
        value = $bindable(1),
        orientation = 'horizontal',
        size = 'default',
        stepsSnippet,
        children,
        ref = $bindable(null),
        onValueChange,
        onStepClick,
        ...restProps
      }: StepperProps = $props()
    
      function getStatus(index: number): StepperStatus {
        const step = steps[index]
        if (step?.error) return 'error'
        if (index + 1 === value) return 'active'
        if (index + 1 < value) return 'completed'
        return 'pending'
      }
    
      function isClickable(index: number): boolean {
        return index + 1 < value
      }
    
      export function goToStep(stepIndex: number) {
        if (stepIndex < 1 || stepIndex > steps.length) return
        const step = steps[stepIndex - 1]
        if (step?.disabled) return
        value = stepIndex
        onValueChange?.(stepIndex)
        onStepClick?.(stepIndex)
      }
    
      setStepperContext({
        orientation: () => orientation,
        size: () => size,
        activeStep: () => value,
        steps: () => steps,
        goToStep,
        isClickable,
        getStatus,
      })
    </script>
    
    <div
      bind:this={ref}
      class={cn('w-full', className)}
      role="tablist"
      aria-orientation={orientation}
      data-orientation={orientation}
      data-uipkge=""
      data-slot="stepper"
      {...restProps}
    >
      {#if stepsSnippet}
        {@render stepsSnippet()}
      {:else if steps.length > 0}
        <ol class={cn('flex', orientation === 'horizontal' ? 'flex-row items-start' : 'flex-col items-stretch')}>
          {#each steps as step, index (step.id)}
            <StepperItem {step} {index} />
          {/each}
        </ol>
      {/if}
    
      {#if children}
        <div class="mt-6 flex-1">
          {@render children({ activeStep: value, steps })}
        </div>
      {/if}
    </div>
    
  • src/lib/components/ui/stepper/StepperItem.svelte5.8 kB
  • src/lib/components/ui/stepper/StepperIndicator.svelte4 kB
  • src/lib/components/ui/stepper/StepperHeader.svelte0.5 kB
  • src/lib/components/ui/stepper/StepperContent.svelte0.8 kB
  • src/lib/components/ui/stepper/StepperTitle.svelte0.5 kB
  • src/lib/components/ui/stepper/StepperDescription.svelte0.5 kB
  • src/lib/components/ui/stepper/StepperStep.svelte2.4 kB
  • src/lib/components/ui/stepper/context.ts1 kB
  • src/lib/components/ui/stepper/stepper.variants.ts1.1 kB
  • src/lib/components/ui/stepper/types.ts0.3 kB
  • src/lib/components/ui/stepper/index.ts1 kB

Raw manifest:https://uipkge.dev/r/svelte/stepper.json