Stepper
UiStepper renders a horizontal or vertical progress indicator for multi-step flows (checkout, onboarding, wizards). Each step derives its status — upcoming, current, or completed — from where activeStep sits within the steps array. The component is uncontrolled by default: bind v-model:active-step to drive it from a parent.
Basic usage
<script setup lang="ts">
import { ref } from 'vue'
const activeStep = ref('profile')
const steps = [
{ id: 'account', label: 'Account', description: 'Create your credentials' },
{ id: 'profile', label: 'Profile', description: 'Tell us about yourself' },
{ id: 'billing', label: 'Billing', description: 'Add a payment method' },
{ id: 'confirm', label: 'Confirm', description: 'Review and finish' },
]
</script>
<template>
<UiStepper
:steps="steps"
v-model:active-step="activeStep" />
</template>
Steps before activeStep render as completed with a check mark; the active step gets aria-current="step"; the rest render as upcoming.
Vertical layout
Set vertical to stack steps in a column, useful for sidebars or narrow layouts.
<template>
<UiStepper :steps="steps" :active-step="activeStep" vertical />
</template>
Linear progression
Set linear to block selecting any step ahead of the current one — users can still navigate back to a completed step, but can't skip forward.
<template>
<UiStepper :steps="steps" v-model:active-step="activeStep" linear />
</template>
Step icons
Give a step an icon (Material Symbols code point) to render it instead of the step number. Completed steps always show a check mark regardless of icon.
<script setup lang="ts">
const steps = [
{ id: 'cart', label: 'Cart', icon: '' },
{ id: 'shipping', label: 'Shipping', icon: '' },
{ id: 'payment', label: 'Payment', icon: '' },
{ id: 'done', label: 'Done', icon: '' },
]
</script>
<template>
<UiStepper :steps="steps" active-step="shipping" />
</template>
Disabled step
Mark a step disabled to remove it from keyboard navigation and block selection entirely, regardless of linear.
<template>
<UiStepper
:steps="[
{ id: 'account', label: 'Account' },
{ id: 'profile', label: 'Profile' },
{ id: 'billing', label: 'Billing', disabled: true },
{ id: 'confirm', label: 'Confirm' },
]"
active-step="profile" />
</template>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | IStepItem[] | — | Step items: { id, label, description?, icon?, disabled? }. |
activeStep | string | first step | The id of the step that should be active. |
vertical | boolean | false | Renders the stepper as a vertical list. |
linear | boolean | false | Blocks selecting a step ahead of the current one. |
customClass | string | string[] | Record<string, boolean> | null | — | Extra classes for the stepper root element. |
Emits: update:activeStep with the selected step's id, used by v-model:active-step.
UiTabs: arrow keys move roving focus between selectable steps (skipping disabled ones, and — in linear mode — steps ahead of the current one), Home/End jump to the first/last selectable step.CSS variables
Set these on :root, or on any wrapper to restyle only the steppers inside it. A pending step's indicator border follows the connector color; current and completed indicators use their background as the border.
:root {
--cffy-stepper-indicator-radius: var(--cffy-radius-md);
--cffy-stepper-connector-thickness: 4px;
}
| Variable | Default | Controls |
|---|---|---|
--cffy-stepper-indicator-size / --cffy-stepper-indicator-radius | 2.25rem / --cffy-radius-full | Indicator size and corners |
--cffy-stepper-indicator-bg-color / --cffy-stepper-indicator-color | --cffy-surface-container / --cffy-muted-a10 | Pending indicator |
--cffy-stepper-current-indicator-bg-color / --cffy-stepper-current-indicator-color | --cffy-primary-a10 / --cffy-on-primary | Current step indicator |
--cffy-stepper-completed-indicator-bg-color / --cffy-stepper-completed-indicator-color | --cffy-primary-a10 / --cffy-on-primary | Completed step indicator |
--cffy-stepper-indicator-font-size / --cffy-stepper-indicator-icon-size | --cffy-fs-2xs / --cffy-fs-lg | Step number and icon |
--cffy-stepper-connector-thickness / --cffy-stepper-connector-color | 2px / --cffy-outline-surface | Line between steps |
--cffy-stepper-completed-connector-color | --cffy-primary-a10 | Line after a completed step |
--cffy-stepper-label-color / --cffy-stepper-current-label-color / --cffy-stepper-completed-label-color | --cffy-muted-a10 / --cffy-on-background / --cffy-on-background | Label of pending, current and completed steps |
--cffy-stepper-label-font-size / --cffy-stepper-label-font-weight | --cffy-fs-2xs / --cffy-fw-600 | Label text |
--cffy-stepper-label-max-width | 12rem | Label and description width in the horizontal layout |
--cffy-stepper-description-color / --cffy-stepper-description-font-size | --cffy-muted-a10 / --cffy-fs-4xs | Description text |
--cffy-stepper-gap | --cffy-space-24 | Space between steps in the vertical layout |
--cffy-stepper-easing / --cffy-stepper-duration | --cffy-ease-decelerate / --cffy-duration-200 | State transitions |