跳转到内容

切换按钮组 toggle-group

通用组件。三层同源:无头内核给出解剖与状态机,Vue 组件与自定义元素只是它的两层外壳,行为完全一致。

示例

基础用法

单选分段控件:条目由 collection 铺开,root 是 radiogroup、条目是 radio;整组只占一个 Tab 位,进组后四个方向键都能走

受控与不可清空

传了 value 就由宿主说了算;单选组再点一次当前项会清空成 null,disallow-empty 把这一手关掉

当前:left
disallow-empty:comfortable,点不成空

多选

multiple 换的是整套 ARIA:root 退回 group、条目退回原生按钮 + aria-pressed,值也从字符串变成数组

当前:bold

禁用

条目一律 aria-disabled 而非原生 disabled:点不动,但焦点落得上去,仍能当方向键的起点

条目来自数据

条目由一份数组渲染,值、文案与禁用都写在数据里;运行期增删条目也照常,删掉的正好是选中项时由宿主把值收拾干净

当前:list

拦下一次切换

受控时 value-change 是唯一出口:宿主不写回,值就原样不动,条件不满足的那一段永远切不过去

当前:draft

整组换一档尺寸

高度、内边距与字号各是一个组件令牌,写在 root 上由整组条目继承,不必逐个条目改

产物

自定义元素<xh-toggle-group>
Vue 组件XhToggleGroupItem XhToggleGroupRoot
组合式函数useToggleGroup
状态机toggleGroupMachine
皮肤@xihan-ui/styles/toggle-group.css

解剖

部件名即 data-part 属性值,也是皮肤的选择器。加粗的是必备部件,不渲染它组件不工作(Web Components 适配器会在诊断通道上报 wc.missing-part)。

data-scope="toggle-group"root · item

Props

属性类型必填说明
collectionToggleGroupNode[]条目数据,显示文本与禁用的事实源。给了它,条目部件只需报 value。 缺省即回到「文本与禁用都写在条目部件上」的老路。
valueToggleGroupValue选中值。给定即受控:内部不再自改,只发 onValueChange。
defaultValueToggleGroupValue
multipleboolean允许多项同时选中;false 时选中一项即挤掉其余。
disabledboolean整组禁用:条目全部 aria-disabled,点击与方向键都不生效。
disallowEmptyboolean不许把值清空:单选模式下点当前选中项不再取消它,多选模式下摘不掉最后一个。 默认 false(可以点成无选中)。
orientationOrientation视觉排布,默认 horizontal。方向键接受的轴与它无关(四个方向键恒响应)。
dirDirection文字方向,默认 ltr;只改写左右方向键的语义,上下键与之无关。
loopboolean方向键走到尽头是否回绕,默认 true。
rovingFocusbooleanroving tabindex,默认开启:整组只占一个 Tab 位,组内靠方向键走。 关掉后每个条目自成一个 Tab 停靠点,方向键不再接管。
onValueChange(details: ToggleGroupValueChangeDetails) => voidvalue 变化意图回调;受控时是唯一出口,非受控随内部写入一并通知。

状态机

状态idle

事件VALUE.SET · ITEM.TOGGLE · ITEM.FOCUS · GROUP.BLUR

connect API

useToggleGroup 产出的对象。getXxxProps() 铺到对应部件的宿主元素上,其余是可读状态与操作入口。

成员类型说明
valuestring[]当前选中集合,恒为数组(单选时长度 ≤ 1)。
collectionreadonly ToggleGroupNodeMeta[]collection 推出的条目元信息,按数据顺序排列;没给 collection 即空数组。
focusedValuestring | null焦点在组外时为 null。
multipleboolean
disabledboolean
isSelected(value: string) => boolean
setValue(next: ToggleGroupValue) => void传单值 / 数组 / null 皆可,内部按 multiple 归一。
getRootProps() => T['element']
getItemProps(props: ToggleGroupItemProps) => T['button']

键盘

规格出处:W3C APG

按键生效条件行为
Tab / Shift+TabrovingFocus 开启(默认)整组只占一个 Tab 位:焦点落到锚点条目,无锚点时先落容器再由它转投
ArrowRight / ArrowDownfocus in group, 组未禁用且 rovingFocus 开启焦点移到下一个可停留条目(禁用项跳过、尽头按 loop 回绕),不改选中;dir=rtl 时改由 ArrowLeft 承担
ArrowLeft / ArrowUpfocus in group, 组未禁用且 rovingFocus 开启焦点移到上一个可停留条目,不改选中;dir=rtl 时改由 ArrowRight 承担
Homefocus in group, 组未禁用且 rovingFocus 开启焦点移到首个可停留条目
Endfocus in group, 组未禁用且 rovingFocus 开启焦点移到末个可停留条目
Enter / Spacefocus on item, 条目未禁用切换该条目;条目是原生 button,这两个键由平台翻成 click

Released under The MIT License