步骤条
概述
用于表示多步骤流程当前进度的步骤条组件。SStepper 将 StepperRoot 一族的 Aria 基础组件(零样式)与 stepperVariants 样式配方(8 个槽位:root/item/trigger/indicator/indicatorIcon/itemContent/separator/title/description,7 种颜色 × 7 种尺寸)组合。在线性模式(默认)下步骤必须按顺序完成——未来步骤被禁用且无法跳过;非线性模式下可自由激活任意步骤。当前步骤通过本地化的 role="status" 实时区域向屏幕阅读器播报,组的 aria-label 在未显式传入时回退到 stepper.ariaLabel 语言包消息。
用法
特性
- 🔁 默认线性模式 —
linear(默认true)禁用不可达的未来步骤并阻止跳步;已完成的历史步骤始终可达 - 🧭 水平 / 垂直 —
orientation切换布局、连接线方向与方向键导航轴 - 🎛️ 受控 / 非受控 —
modelValue+update:modelValue或defaultValue(默认1);根插槽暴露goToStep/nextStep/prevStep/hasNext/hasPrev/totalSteps等 - 🖱️ 点击、Enter 或 Space 选中步骤;方向键移动焦点(感知方向并遵循
dir),Home/End 跳到首/尾可达步骤 - ♿ 默认无障碍 —
role="group"与本地化aria-label回退、激活项的aria-current="step"、trigger/title/description 之间的aria-labelledby/aria-describedby关联,以及role="status"实时区域(stepper.stepOf消息) - 🧩 Aria/样式拆分 —
StepperCompact聚合 7 个基础组件并暴露 6 个*Props通道(item/trigger/indicator/separator/title/description);step始终由 item 顺序推导 - 🎨 8 槽位样式 — root/item/trigger/indicator/indicatorIcon/itemContent/separator/title/description,7 色(primary/destructive/success/warning/info/carbon/secondary/accent)与 7 尺寸(xs–2xl)
- 🌐 默认本地化 — 实时区域、组
aria-label与指示器默认内容均使用useLocaleMessages(stepper.step/stepper.ariaLabel/stepper.stepOf)
组件家族
SStepper(styled)— 入口包装;stepperVariants配方配合动态 8 槽位转发与useForwardListeners事件合并;镜像linear默认值,避免缺失的布尔 prop 被转成falseStepperRoot(Aria)— 状态所有者:基于modelValue/defaultValue的useControllableState、totalSteps/currentStep推导、canGoToStep线性门控与goToStep/nextStep/prevStepAPI;渲染role="group"、data-linear、data-orientation、aria-label回退与VisuallyHidden实时区域StepperItem(Aria)—step(从 1 开始)、disabled、completed;按位置推导data-state(completed/active/inactive),按linear+disabled推导isFocusableStepperTrigger(Aria)— 默认为button;mousedown.left加 Enter/Space 选中,方向键/Home/End 导航;对不可达步骤渲染disabled/data-disabled/tabindex="-1"并注册进根集合StepperIndicator(Aria)— 默认为span;默认内容是本地化的stepper.step消息(第 {step} 步)StepperTitle/StepperDescription(Aria)— 默认为h4/p;暴露被 trigger 的aria-labelledby/aria-describedby消费的idStepperSeparator(Aria)— 基于SeparatorRoot的连接线;默认decorative,方向与data-state来自 root/item 上下文StepperCompact(Aria)— 聚合复合组件;以step: index + 1规范化 items,默认指示器对已完成步骤显示对勾图标(经 ConfigProvidericonRender渲染lucide:check),否则显示步骤序号,默认标题回退为Step {n};插槽:item/indicator/title/description/separator
演示
基础
垂直
线性
自定义样式
- 01 Basic — 基于
items的受控v-model - 02 Vertical —
orientation="vertical"布局 - 03 Linear — 带上一步/下一步按钮的顺序完成
- 04 Custom styling — 8 槽位
ui覆盖
API
Aria 层
9Stepper
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | Partial<StepperUi> | — | 该组件的按槽类重写。 |
items | StepperItemData[] | — | 由该组件渲染的项。 |
itemProps | Omit<StepperItemProps, 'step'> | — | 转发给 `item` 元素的属性。`step` 由项的顺序推导而来,无法被覆盖。 |
triggerProps | StepperTriggerProps | — | 转发给触发元素的属性。 |
indicatorProps | StepperIndicatorProps | — | 转发给 indicator 元素的属性。 |
separatorProps | SeparatorRootProps | — | 转发给分隔符元素的属性。 |
titleProps | StepperTitleProps | — | 传递给 title 元素的属性。 |
descriptionProps | StepperDescriptionProps | — | 已将属性转发至 description 元素。 |
defaultValue | number | 1 | 初始渲染时应处于活动状态的步骤的值。 |
modelValue | number | — | 要激活的步骤的受控值。可作为 `v-model` 进行绑定。 |
orientation | DataOrientation | 'horizontal' | 步进器的方向。 |
dir | Direction | — | 步进电机的读数方向。 |
linear | boolean | true | 步骤是否必须按顺序完成。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | number | 当模型值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
item | StepperItemData & { step: number; state: StepperState; } | 项插槽的自定义内容。 |
indicator | StepperItemData & { step: number; state: StepperState; } | 指示器插槽的自定义内容。 |
title | StepperItemData & { step: number; state: StepperState; } | 标题槽位的自定义内容。 |
description | StepperItemData & { step: number; state: StepperState; } | 描述字段的自定义内容。 |
separator | StepperItemData & { step: number; state: StepperState; } | 分隔符槽位的自定义内容。 |
StepperCompact
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
items | StepperItemData[] | — | 由该组件渲染的项。 |
itemProps | Omit<StepperItemProps, 'step'> | — | 转发给 `item` 元素的属性。`step` 由项的顺序推导而来,无法被覆盖。 |
triggerProps | StepperTriggerProps | — | 转发给触发元素的属性。 |
indicatorProps | StepperIndicatorProps | — | 转发给 indicator 元素的属性。 |
separatorProps | SeparatorRootProps | — | 转发给分隔符元素的属性。 |
titleProps | StepperTitleProps | — | 传递给 title 元素的属性。 |
descriptionProps | StepperDescriptionProps | — | 已将属性转发至 description 元素。 |
defaultValue | number | 1 | 初始渲染时应处于活动状态的步骤的值。 |
modelValue | number | — | 要激活的步骤的受控值。可作为 `v-model` 进行绑定。 |
orientation | DataOrientation | 'horizontal' | 步进器的方向。 |
dir | Direction | — | 步进电机的读数方向。 |
linear | boolean | true | 步骤是否必须按顺序完成。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | number | 当模型值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
item | StepperItemData & { step: number; state: StepperState; } | 项插槽的自定义内容。 |
indicator | StepperItemData & { step: number; state: StepperState; } | 指示器插槽的自定义内容。 |
title | StepperItemData & { step: number; state: StepperState; } | 标题槽位的自定义内容。 |
description | StepperItemData & { step: number; state: StepperState; } | 描述字段的自定义内容。 |
separator | StepperItemData & { step: number; state: StepperState; } | 分隔符槽位的自定义内容。 |
StepperDescription
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
StepperIndicator
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
StepperItem
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
step | number | — | 步骤索引,从 `1` 开始。 |
disabled | boolean | — | 当值为 `true` 时,禁止用户与该步骤进行交互。 |
completed | boolean | — | 显示该步骤是否已完成。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
StepperRoot
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
defaultValue | number | 1 | 初始渲染时应处于活动状态的步骤的值。 |
modelValue | number | — | 要激活的步骤的受控值。可作为 `v-model` 进行绑定。 |
orientation | DataOrientation | 'horizontal' | 步进器的方向。 |
dir | Direction | — | 步进电机的读数方向。 |
linear | boolean | true | 步骤是否必须按顺序完成。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | number | 当模型值发生变化时触发。 |
StepperSeparator
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
orientation | DataOrientation | — | 组件的排列方向。
可选值为 `vertical` 或 `horizontal`。默认值为 `horizontal`。 |
decorative | boolean | — | 该组件是否纯属装饰性。<br>当值为 `true` 时,将更新与无障碍相关的属性,
从而将渲染后的元素从无障碍树中移除。 |
StepperTitle
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
StepperTrigger
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
说明
架构与对标差异
StepperRoot 拥有完整状态机(受控状态、有序 item 集合、线性门控),所有基础组件保持零样式,仅 UI 包装注入 stepperVariants 类名。isFocusable 逐项推导(disabled || (!linear && step > currentStep + 1))并镜像为 DOM 上的 disabled/data-disabled/tabindex,因此不可达步骤既不可点击也不在 Tab 序列中。方向键导航使用 useArrowNavigation(loop: false)并遵循 orientation/dir;线性模式下焦点不会落在被禁用的未来步骤上。完成对勾图标需要 ConfigProvider 提供 iconRender(默认 Icon 组件不渲染任何内容),否则已完成步骤回退为序号。实时区域与 aria-label 回退经 useLocaleMessages 本地化,而 shadcn/ui 的 stepper 区块硬编码了英文文本。
| 能力 | VeanUI | shadcn/ui (blocks) | Ant Design Steps | Element Plus Steps | Mantine Stepper |
|---|---|---|---|---|---|
| Aria/样式拆分 | ✅ | — | — | — | — |
| 线性模式(按顺序完成) | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| 水平 / 垂直方向 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 方向键导航(Home/End) | ✅ | — | — | — | — |
本地化实时区域 + 组 aria-label | ✅ | ⚠️ | — | — | — |
| 受控 / 非受控 | ✅ | — | ⚠️ | ⚠️ | ✅ |
| 复合组件 + 逐部件 props | ✅ | — | — | — | — |
每步 completed/disabled | ✅ | ✅ | ✅ | ✅ | ✅ |
⚠️ = 部分支持(AntD 用 status prop 代替线性门控;Element Plus 提供 process-status/finish-status 但没有导航门控;shadcn/ui 的 stepper 区块用硬编码英文渲染状态文本,且不是库组件)。
注意事项
StepperItem的step必须从 1 开始且连续:canGoToStep与焦点逻辑按step - 1索引有序集合。Compact 会自动按 item 顺序规范化;自定义 Aria 组合必须保持 step 连续。itemProps有意省略step——它由 item 顺序推导,无法覆盖。- 线性模式下仅当前步与下一步可达;
goToStep/nextStep对不可达目标静默忽略,请通过hasNext/hasPrev或nextStep/prevStep辅助方法驱动导航。 - 实时区域(
role="status")仅在totalSteps > 0时渲染;当默认语言包消息不合适时请为根元素显式传入aria-label。 - 未配置 ConfigProvider
iconRender时默认指示器回退为步骤序号;配置后即可渲染完成对勾图标。 - 方向键导航会跳过
disabled步骤,但集合仍然有序;完全禁用的步骤条也应暴露组aria-label。
常见问题
如何让未来步骤可点击?
设置 linear="false"——无论当前位置如何,每个步骤都可聚焦、可选中:
<SStepper :items="items" :linear="false" />如何用按钮驱动步骤条?
绑定 v-model 并从根插槽取 hasNext/hasPrev 来控制按钮:
<SStepper v-model="value" :items="items" linear>
<template #default="{ hasNext, hasPrev, nextStep, prevStep }">
<!-- 自定义布局,调用 nextStep() / prevStep() -->
</template>
</SStepper>如何渲染垂直步骤条?
设置 orientation="vertical"——连接线与方向键导航轴随之切换:
<SStepper :items="items" orientation="vertical" />如何让某个步骤无论位置都显示为完成?
在 item 数据中传入 completed;显式 completed 优先于位置推导的状态:
<SStepper :items="[{ title: 'Account', completed: true }, { title: 'Profile' }]" />如何自定义指示器内容?
使用 indicator 插槽——它接收 item 数据、step 与 state:
<SStepper :items="items">
<template #indicator="{ state, step }">
<span>{{ state === 'completed' ? '✓' : step }}</span>
</template>
</SStepper>如何本地化状态播报?
实时区域与组 aria-label 跟随 ConfigProvider 的语言环境(stepper.stepOf / stepper.ariaLabel);需要时可用 aria-label 按实例覆盖:
<SStepper :items="items" aria-label="Checkout progress" />