Steps
Import
Section titled “Import”Steps uses a compound component pattern. The Step sub-component is re-exported from the same module.
import { Steps, Step } from '@delightstack/components';import type { StepsContext } from '@delightstack/components';Basic Usage
Section titled “Basic Usage”View code
<script> import { Steps, Step } from '@delightstack/components'; import { Button } from '@delightstack/components';
let current = $state(1);</script>
<Steps bind:current> <Step title="Account" description="Create your account" /> <Step title="Profile" description="Set up your profile" /> <Step title="Review" description="Review details" /> <Step title="Complete" description="All done" /></Steps>
<Button outline onclick={() => current = Math.max(0, current - 1)}>Back</Button><Button onclick={() => current = Math.min(4, current + 1)}>Next</Button>Examples
Section titled “Examples”Clickable Steps
Section titled “Clickable Steps”Allow users to navigate back to completed steps by clicking on them.
View code
<script> import { Steps, Step } from '@delightstack/components';
let current = $state(1);</script>
<Steps bind:current clickable> <Step title="Account" /> <Step title="Profile" /> <Step title="Review" /> <Step title="Complete" /></Steps>Non-Linear Navigation
Section titled “Non-Linear Navigation”Allow jumping to any step, not just completed ones.
View code
<script> import { Steps, Step } from '@delightstack/components';
let current = $state(0);</script>
<Steps bind:current clickable linear={false}> <Step title="Overview" /> <Step title="Details" /> <Step title="Summary" /></Steps>Vertical Layout
Section titled “Vertical Layout”Stack steps vertically for sidebar or mobile layouts.
View code
<script> import { Steps, Step } from '@delightstack/components'; import { Button } from '@delightstack/components';
let current = $state(1);</script>
<Steps bind:current orientation="vertical"> <Step title="Cart" description="Review items" /> <Step title="Shipping" description="Enter address" /> <Step title="Payment" description="Add payment method" /> <Step title="Confirm" description="Place order" /></Steps>
<Button outline onclick={() => current = Math.max(0, current - 1)}>Back</Button><Button onclick={() => current = Math.min(4, current + 1)}>Next</Button>Error and Optional Steps
Section titled “Error and Optional Steps”Mark steps with error states or as optional.
View code
<script> import { Steps, Step } from '@delightstack/components';
let current = $state(2);</script>
<Steps bind:current> <Step title="Account" /> <Step title="Verification" error /> <Step title="Preferences" optional /> <Step title="Done" /></Steps>Wizard Mode with Step Content
Section titled “Wizard Mode with Step Content”Render content for each step, shown when that step is active.
View code
<script> import { Steps, Step } from '@delightstack/components'; import { Button, Input } from '@delightstack/components';
let current = $state(0);</script>
<Steps bind:current orientation="vertical"> <Step title="Personal Info"> <Input label="Full Name" /> <Input label="Email" type="email" /> <Button onclick={() => current++}>Next</Button> </Step> <Step title="Address"> <Input label="Street" /> <Input label="City" /> <Button outline onclick={() => current--}>Back</Button> <Button onclick={() => current++}>Next</Button> </Step> <Step title="Confirm"> <p>All done!</p> <Button outline onclick={() => current--}>Back</Button> </Step></Steps>Overflow
Section titled “Overflow”When horizontal steps can’t fit their container, the row becomes a snap-scrollable strip with edge fades hinting at the clipped steps. On devices with a fine pointer, chevron buttons appear at the edges to page through (no clunky horizontal scrollbar); on touch devices the strip swipes. The current step automatically scrolls into view when it changes, and nothing changes when the steps fit.
View code
<script> import { Steps, Step } from '@delightstack/components';
let current = $state(2);</script>
<!-- Constrained container: the steps overflow into a scroll strip --><div style="max-width: 28rem;"> <Steps bind:current clickable> <Step title="Account" description="Sign up" /> <Step title="Profile" description="About you" /> <Step title="Team" description="Invite members" /> <Step title="Billing" description="Payment details" /> <Step title="Plan" description="Pick a tier" /> <Step title="Integrations" description="Connect tools" /> <Step title="Review" description="Check settings" /> <Step title="Launch" description="Go live" /> </Steps></div>Skeleton Loading
Section titled “Skeleton Loading”View code
<Steps skeleton={loading} skeleton_count={4}>…</Steps>Steps (Container)
Section titled “Steps (Container)”| Prop | Type | Default | Description |
|---|---|---|---|
current | number | 0 | The current active step index ($bindable) |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout orientation |
clickable | boolean | false | Whether completed steps are clickable for navigation |
linear | boolean | true | Whether navigation is restricted to sequential order |
size | '0' | '1' | '2' | '3' | '1' | Size variant |
skeleton | boolean | false | Show skeleton shimmer placeholders |
skeleton_count | number | 4 | Number of skeleton placeholder steps |
id | string | auto | Element ID |
class | string | '' | Additional CSS classes |
children | Snippet | undefined | Step children |
Step (Item)
Section titled “Step (Item)”| Prop | Type | Default | Description |
|---|---|---|---|
title | string | '' | The title text for this step |
description | string | '' | Optional description text below the title |
optional | boolean | false | Whether this step is optional |
error | boolean | false | Whether this step is in an error state |
children | Snippet | undefined | Step content (for wizard mode, shown when active) |
Events
Section titled “Events”Steps (Container)
Section titled “Steps (Container)”| Event | Detail | Description |
|---|---|---|
onchange | { step: number } | Fires when the active step changes |
oncomplete | none | Fires when all steps are completed |
StepsContext
Section titled “StepsContext”interface StepsContext { current: number; orientation: 'horizontal' | 'vertical'; clickable: boolean; linear: boolean; size: string; totalSteps: number; register: () => number; navigate: (index: number) => void;}Accessibility
Section titled “Accessibility”- Container uses
role="navigation"witharia-label="Progress steps" - Each step uses
role="listitem"witharia-current="step"for the active step - Step indicators show completion state with
aria-label(e.g. “Step 1: Account - Completed”) - Clickable steps are focusable
<button>elements - Error steps are announced via
aria-labelwith error state - Optional steps display “(Optional)” text
- Focus-visible outlines on clickable step indicators
- Connector lines between steps indicate progress visually