ToggleGroup 切换按钮组
一排 Toggle 切换按钮,由组统一管理谁按下。用在「对齐方式」「视图切换」这类几个选项里选一个, 或「加粗 / 斜体 / 下划线」这类可以同时按下几个的工具栏分组。选项要随表单提交时用 RadioGroup 单选组。
默认 type="single":同一时间最多按下一项,点另一项时原来那项弹起;再点已按下的那项取消选择(value 变为空串)。
<pt-toggle-group variant="outline" value="center" aria-label="对齐方式">
<pt-toggle value="left">左对齐</pt-toggle>
<pt-toggle value="center">居中</pt-toggle>
<pt-toggle value="right">右对齐</pt-toggle>
</pt-toggle-group>type="multiple" 时各项独立按下,value 是字符串数组(HTML 里写成逗号分隔)。组上的 size / variant 回写到每一项。
<pt-toggle-group type="multiple" size="sm" value="bold,underline" aria-label="文字样式">
<pt-toggle value="bold">加粗</pt-toggle>
<pt-toggle value="italic">斜体</pt-toggle>
<pt-toggle value="underline">下划线</pt-toggle>
</pt-toggle-group>orientation="vertical" 时竖排、↑ ↓ 移动焦点。禁用的项不可点,方向键跳过它;组上的 disabled 禁用全部项。
<pt-toggle-group orientation="vertical" variant="outline" value="list" aria-label="视图">
<pt-toggle value="list">列表</pt-toggle>
<pt-toggle value="grid" disabled>网格</pt-toggle>
<pt-toggle value="board">看板视图</pt-toggle>
</pt-toggle-group>结构
pt-toggle-group 里直接放若干 pt-toggle,每一项都写上 value —— 组的 value 靠它对应,缺了 value 的项不能被选中。 项必须是组的直接子元素:隔了一层容器的 pt-toggle 不归组管,照常自己切换。
组上写了 variant / size 时回写到每一项,覆盖项自己写的(组级优先,之后再改项上的同名属性也会被组改回去); 组上没写时各项用自己的,可以逐项设置。组上的 disabled 禁用全部项, 但不改写项自己的 disabled,解除后各项回到自己的状态。
受控值
受控属性是 value,事件是 ptChange:
type | value 的形状 | 一个都没按下时 |
|---|---|---|
single(默认) | 字符串:按下那一项的 value | '' |
multiple | 字符串数组:按下的各项的 value | [] |
- Vue:
<PtToggleGroup v-model="align"> - Angular:
<pt-toggle-group [(ngModel)]="align">,standalone 组件要在imports里加上TextValueAccessor - React:
<PtToggleGroup value={align} onPtChange={e => setAlign(e.detail)}>
数组只能用 JS / 框架绑定赋值;在 HTML 里写 multiple 的初始值时用逗号分隔:value="bold,underline" (各段去掉首尾空白)。因此 multiple 下项的 value 本身不要含逗号。
ptChange 只在用户点击时发;外部直接改 value 只改状态,不发事件。组的 value 是按下态的唯一来源: 直接改组内某项的 pressed(业务代码或框架绑定)会被组按 value 改回去,要改按下态请改组的 value。multiple 下组件写回的总是一个新数组。 组内的 pt-toggle 不发它自己的 ptChange,ptChange 照常冒泡,外层容器可以做事件委托。
single 下再点已按下的那项会取消选择(与 Radix ToggleGroup 一致)。需要「总有一项选中」时用 Tabs 标签页 的 segmented 变体或 RadioGroup 单选组。
键盘操作
整组只占一个 Tab 停靠点:有按下的项停在第一个按下的项上,否则停在第一个可用项。
| 按键 | 行为 |
|---|---|
← →(horizontal,默认) | 在各项之间移动焦点,RTL 下对调;不改变按下态 |
↑ ↓(vertical) | 同上 |
| Home / End | 移到第一项 / 最后一项 |
| Space / Enter | 切换当前聚焦的项 |
禁用项被跳过。loop(默认开)决定到头时是否回到另一端,原生 HTML 里关掉写 loop="false"。
无障碍
single与multiple语义一致:组是role="group",各项内部按钮是切换按钮(aria-pressed)。single不用radiogroup/radio(Radix ToggleGroup 用了,这里有意不跟):WAI-ARIA 的单选组要求 「选中后不能靠再次激活取消」「方向键移焦点的同时选中」,而切换按钮组恰好相反 —— 再点已按下项会取消选择, 方向键只移焦点、要按 Space / Enter 才切换。读屏若宣布成「单选按钮」,用户会按单选组的习惯操作而得到意外结果。 需要真正的单选语义(总有一项选中、方向键即选中、可随表单提交)时用 RadioGroup 单选组。- 页面上没有可见的组标题时给组写
aria-label(包装层里是ariaLabelText);纯图标的项同样要各自写aria-label。
API
属性
| 属性 | Attribute | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
ariaLabelText | aria-label | string | undefined | — | 无障碍名称:原生 HTML 里写 aria-label,React / Vue / Angular 包装层里属性名是 ariaLabelText。 页面上没有可见的组标题时必须给 —— 读屏进入这一组时先念它。 |
disabled | disabled | boolean | false | 禁用整组:全部项不可点、不可聚焦。不改写各项自己的 `disabled`,解除后各项回到自己的状态 |
inheritedDisabled | inherited-disabled | boolean | false | 外层 pt-field-set 下发的禁用。内部继承通道:由它以 attribute 维护,不建议使用方直接写。 有效禁用是 `disabled` 与它的并集;父元素只写这一条、不碰 `disabled`,读 `el.disabled` 得到的始终是使用方自己写的值 |
loop | loop | boolean | true | 方向键到头后是否回到另一端。默认为真:原生 HTML 里关掉它写 `loop="false"` |
orientation | orientation | "horizontal" | "vertical" | 'horizontal' | 排列方向,同时决定方向键:horizontal 横排、← →(默认);vertical 竖排、↑ ↓ |
size | size | "lg" | "md" | "sm" | undefined | — | 尺寸档位,三档对应 24 / 32 / 40 的控件刻度。回写规则同 `variant`:写了组级优先,不写时各项用自己的(默认 md) |
type | type | "multiple" | "single" | 'single' | 选择方式: - `single`:同一时间最多按下一项,按下另一项时原来那项弹起;再点已按下的那项会取消选择(`value` 变为空串); - `multiple`:各项独立按下 / 弹起。 |
value | value | string | string[] | '' | 按下着的项的 `value`。 - `single`:字符串,空串表示一个都没按下; - `multiple`:字符串数组。数组只能用 JS / 框架绑定赋值;写成 HTML attribute 时用**逗号分隔** (`value="bold,italic"`,各段去掉首尾空白),因此 multiple 下项的 `value` 本身不要含逗号。 用户点击时组件自己改写它(multiple 下总是写回一个新数组)并发 `ptChange`;外部直接赋值不发事件。 |
variant | variant | "default" | "outline" | undefined | — | 视觉变体:default 透明底;outline 带 1px 描边。写了就回写到每一项(组级优先,覆盖项自己写的 variant, 项之后再改也会被改回去);不写时各项用自己的 variant(默认 default)。写过再撤掉时各项保留最后一次回写的值 |
事件
| 事件 | detail 类型 | 说明 |
|---|---|---|
ptChange | string | string[] | 用户点击某一项改变了按下态后触发,detail 是新的 `value`(`single` 为字符串、取消选择时为空串; `multiple` 为字符串数组)。Vue 的 v-model 与 Angular 的 ngModel 绑在它上面。外部直接改 `value` 不触发。 冒泡(组件默认):切换按钮组不会自我嵌套,组内的 `pt-toggle` 也不发自己的 `ptChange`,冒泡不会串到别的绑定上。 |
方法
| 方法 | 说明 |
|---|---|
refresh() => Promise<void> | 重新按 `value` 同步各项的按下态与 Tab 停靠点。子项增删、改 value / disabled,或组内某项的 `pressed` 被外部改写时 组件自己会调,一般不需要手动调用 |
插槽
| 名称 | 说明 |
|---|---|
(默认) | 若干 `pt-toggle`,每个都要写 `value`(缺了 `value` 的项不能被选中) |
可定制的内部元素(::part())
| part | 说明 |
|---|---|
base | 排布各项的容器 |