分段控件
概述
由两个或更多互斥选项组成的线性控件,以统一的形态呈现,并带有跟随当前选中项的滑动指示器。适用于紧凑的分段选择场景——时间范围、视图切换或任何小型单选选项——且选择需要立即生效。若需要一组独立的双态按钮(单选或多选),使用 SToggleGroup;若只是普通的标签页内容面板,使用 STabs。
用法
特性
- 🎯 互斥单选——同一时刻只有一个分段处于选中态,由
useControllableState支撑 - 🎚 受控 / 非受控——
v-model与defaultValue(泛型值通过T extends SegmentOptionData获得类型安全) - 🧩 数据驱动组合——传入
items,由 AriaSegmentCompact负责遍历与指示器布局 - ✨ 可选滑动指示器——
enableIndicator(默认true),可通过indicator插槽完全自定义 - ⌨️ Roving focus 键盘导航——方向键在分段间移动焦点,
loop循环回绕,RTL 下方向自动反转 - 🎨 6 尺寸 × 2 方向 × 2 形状(square/rounded)× 2 填充(auto/full)——由
segmentVariants提供 - 🧩
ui各插槽类覆盖(root/list/trigger/indicator/indicatorContent),支持条目级disabled - ♿
role="tab"+aria-selected并反射data-state,axe 零违规
组件族系
SSegment——样式包装层,透传 props 给 Aria compact 并注入segmentVariants类SegmentRoot/SegmentList/SegmentTrigger/SegmentIndicator(Aria)— 包装 Tabs 的领域基元;DOM 使用data-vean-segment-*SegmentCompact(Aria)——由上述基元数据驱动组合;无样式使用时从@vean/aria/segment导入
演示
基础
图标
API
Aria 层
6Segment<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
ui | Partial<SegmentUi> | — | 该组件的按槽类重写。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
shape | SegmentShape | — | 组件的结构。 |
fill | SegmentFill | — | 填充。 |
items | T[] | — | 由该组件渲染的项。 |
enableIndicator | boolean | — | 是否启用指示器。 |
listProps | SegmentListProps | — | 转发给列表元素的属性。 |
triggerProps | SegmentTriggerProps | — | 转发给触发元素的属性。 |
indicatorProps | SegmentIndicatorProps | — | 转发给 indicator 元素的属性。 |
modelValue | T['value'] | null | — | 用于激活的选项卡的受控值。可作为 `v-model` 进行绑定。 |
defaultValue | T['value'] | null | — | 初始渲染时应处于活动状态的标签页的值。当您无需控制标签页的状态时使用此选项 |
activationMode | TabsActivationMode | automatic | Tab 键是自动激活(获得焦点时)还是手动激活(点击时)。 |
unmountOnHide | boolean | `true` | 当值为 `true` 时,该元素将在关闭状态下被卸载。 |
dir | Direction | — | 项目之间的导航方向。 |
loop | boolean | false | 键盘导航是否应循环往复 |
orientation | DataOrientation | — | 该组的取向。主要是为了确保箭头导航能据此正确进行(左右与上下)。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | Exclude<T, undefined> | 当值发生变化时调用的事件处理程序 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
item | T & { selected: boolean; } | 项插槽的自定义内容。 |
indicator | — | 指示器插槽的自定义内容。 |
SegmentCompact<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
items | T[] | — | 由该组件渲染的项。 |
enableIndicator | boolean | — | 是否启用指示器。 |
listProps | SegmentListProps | — | 转发给列表元素的属性。 |
triggerProps | SegmentTriggerProps | — | 转发给触发元素的属性。 |
indicatorProps | SegmentIndicatorProps | — | 转发给 indicator 元素的属性。 |
modelValue | T['value'] | null | — | 用于激活的选项卡的受控值。可作为 `v-model` 进行绑定。 |
defaultValue | T['value'] | null | — | 初始渲染时应处于活动状态的标签页的值。当您无需控制标签页的状态时使用此选项 |
activationMode | TabsActivationMode | automatic | Tab 键是自动激活(获得焦点时)还是手动激活(点击时)。 |
unmountOnHide | boolean | `true` | 当值为 `true` 时,该元素将在关闭状态下被卸载。 |
dir | Direction | — | 项目之间的导航方向。 |
loop | boolean | false | 键盘导航是否应循环往复 |
orientation | DataOrientation | — | 该组的取向。主要是为了确保箭头导航能据此正确进行(左右与上下)。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | Exclude<T, undefined> | 当值发生变化时调用的事件处理程序 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
item | T & { selected: boolean; } | 项插槽的自定义内容。 |
indicator | — | 指示器插槽的自定义内容。 |
SegmentIndicator
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
SegmentList
SegmentRoot<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
modelValue | T | — | 用于激活的选项卡的受控值。可作为 `v-model` 进行绑定。 |
defaultValue | T | — | 初始渲染时应处于活动状态的标签页的值。当您无需控制标签页的状态时使用此选项 |
activationMode | TabsActivationMode | automatic | Tab 键是自动激活(获得焦点时)还是手动激活(点击时)。 |
unmountOnHide | boolean | `true` | 当值为 `true` 时,该元素将在关闭状态下被卸载。 |
dir | Direction | — | 项目之间的导航方向。 |
loop | boolean | false | 键盘导航是否应循环往复 |
orientation | DataOrientation | — | 该组的取向。主要是为了确保箭头导航能据此正确进行(左右与上下)。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | Exclude<T, undefined> | 当值发生变化时调用的事件处理程序 |
SegmentTrigger
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
value | DefinedValue | — | 一个将触发器与内容关联起来的唯一值。 |
disabled | boolean | — | 当值为 `true` 时,禁止用户与该选项卡进行交互。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
注意
架构与行业对标差异
SegmentCompact 组合了 Aria 的 SegmentRoot/SegmentList/SegmentTrigger/SegmentIndicator 基元(各自包装对应的 Tabs 部件):负责遍历 items、转发 listProps/triggerProps/indicatorProps,并暴露 item/indicator 插槽。SegmentTrigger 沿用 Tabs 的 ARIA 模式(role="tab" + 焦点漫游),因此 loop 与 dir(RTL)行为与 Tabs 完全一致。SSegment 是薄包装层,仅计算 segmentVariants(tabsVariants 的别名)并调用 provideSegmentUi。指示器通过异步布局测量定位(resize observer + post-flush watch),因此在挂载后一帧出现。segment 对应分段控件模式;各对标库原生提供该模式,唯一例外是 shadcn,通常以 Tabs 替代。
| 能力 | VeanUI | Ant Design | Element Plus | Mantine | Naive UI | shadcn |
|---|---|---|---|---|---|---|
| Aria/styled 分离 | ✅ | — | — | — | — | — |
| 单选(互斥) | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 受控 / 非受控 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 数据驱动 items | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 滑动指示器 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Roving focus 方向键 | ✅ | ✅ | ✅ | ✅ | — | — |
| Loop 循环导航 | ✅ | — | — | — | — | — |
| RTL 方向感知 | ✅ | — | — | — | — | — |
| 方向(竖排) | ✅ | — | — | ✅ | — | — |
| 尺寸 × 形状 × 填充 | ✅ | — | — | ✅ | — | — |
| 条目级禁用 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 自定义条目 / 指示器插槽 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
使用注意
loop与unmountOnHide默认true;enableIndicator默认true。设置:enable-indicator="false"可隐藏滑动指示器(此时选中态通过data-state样式规则体现)。- 指示器经异步布局测量定位——选中项变化后一帧才渲染到位。
- 分段使用 Tabs ARIA 模式(
role="tab"+aria-selected),应避免将分段嵌套在其它 Tabs 类控件内部。 defaultValue仅在挂载时读取,后续变化会被忽略(外部控制请使用v-model)。- 仅含图标的条目请补充
aria-label,确保分段有可访问名称。 unmountOnHide仅在挂载了内容面板时才有意义;单独的SSegment不渲染内容区。
常见问题
SSegment 与 SToggleGroup 有什么区别?
SSegment 是带滑动指示器的互斥单选分段控件——同一时刻仅一项选中。SToggleGroup 协调一组相互独立的切换按钮,支持单选或多选,无指示器。
如何禁用滑动指示器?
传入 :enable-indicator="false"。此时选中项改由 data-selected 样式规则高亮。
如何让方向键循环回绕?
保持 loop(默认 true)即可——焦点从最后一个分段回绕到第一个,反之亦然。禁用分段会被自动跳过。
如何外部控制选中值?
双向控制绑定 v-model;仅传入 defaultValue 则为非受控用法。用 items 声明选项,每个条目支持 value、label 与 disabled。
可以自定义指示器与条目的样式吗?
可以——indicator 插槽替换默认指示器内容;item 插槽接收 { ...item, active } 支持完全自定义;ui.root / ui.list / ui.trigger / ui.indicator 提供各插槽类覆盖。