Components

Stepper

Guide users through a sequence of steps with UiStepper.

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: '&#xe8cc;' },
  { id: 'shipping', label: 'Shipping', icon: '&#xe8ca;' },
  { id: 'payment', label: 'Payment', icon: '&#xe870;' },
  { id: 'done', label: 'Done', icon: '&#xe5ca;' },
]
</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

PropTypeDefaultDescription
stepsIStepItem[]—Step items: { id, label, description?, icon?, disabled? }.
activeStepstringfirst stepThe id of the step that should be active.
verticalbooleanfalseRenders the stepper as a vertical list.
linearbooleanfalseBlocks selecting a step ahead of the current one.
customClassstring | 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.

Keyboard support mirrors 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;
}
VariableDefaultControls
--cffy-stepper-indicator-size / --cffy-stepper-indicator-radius2.25rem / --cffy-radius-fullIndicator size and corners
--cffy-stepper-indicator-bg-color / --cffy-stepper-indicator-color--cffy-surface-container / --cffy-muted-a10Pending indicator
--cffy-stepper-current-indicator-bg-color / --cffy-stepper-current-indicator-color--cffy-primary-a10 / --cffy-on-primaryCurrent step indicator
--cffy-stepper-completed-indicator-bg-color / --cffy-stepper-completed-indicator-color--cffy-primary-a10 / --cffy-on-primaryCompleted step indicator
--cffy-stepper-indicator-font-size / --cffy-stepper-indicator-icon-size--cffy-fs-2xs / --cffy-fs-lgStep number and icon
--cffy-stepper-connector-thickness / --cffy-stepper-connector-color2px / --cffy-outline-surfaceLine between steps
--cffy-stepper-completed-connector-color--cffy-primary-a10Line 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-backgroundLabel of pending, current and completed steps
--cffy-stepper-label-font-size / --cffy-stepper-label-font-weight--cffy-fs-2xs / --cffy-fw-600Label text
--cffy-stepper-label-max-width12remLabel and description width in the horizontal layout
--cffy-stepper-description-color / --cffy-stepper-description-font-size--cffy-muted-a10 / --cffy-fs-4xsDescription text
--cffy-stepper-gap--cffy-space-24Space between steps in the vertical layout
--cffy-stepper-easing / --cffy-stepper-duration--cffy-ease-decelerate / --cffy-duration-200State transitions
Copyright © 2026