Toggle 切换按钮
在按下和未按下状态之间切换的按钮。
用法
切换点赞状态
组件结构
加粗的是必需部件。
data-scope="toggle":root
示例
变体
默认与幽灵外观
仅图标
为每个图标按钮提供可访问名称
尺寸
提供三种尺寸
禁用
保留禁用前的状态
受控状态
由外部状态控制按下值
设计指引
何时使用
- 切换立即生效的格式、视图或工具状态。
- 操作需要保留当前状态时。
何时不用
特性
- 使用
aria-pressed表达当前状态。 - 支持受控和非受控状态。
- 支持变体、颜色、尺寸、仅图标和全宽外观;缺省变体是中性淡底
subtle。 - 按下态是品牌淡底配淡底前景,悬停与按压在同一淡底上加深;只有
solid变体在按下时才是品牌实心,未按下时按ghost取面。 - 禁用后保留当前按下状态。
组合
最佳实践
- 标签应说明切换后影响的功能。
- 仅图标按钮必须提供
aria-label。 - 按下状态不能只依赖颜色区分。
反模式
- 不要用切换按钮表示当前标签页。
- 不要将切换按钮作为表单开关使用。
API 参考
产物
| 层 | 值 |
|---|---|
| 自定义元素 | <xh-toggle> |
| Vue 组件 | XhToggle |
| 组合式函数 | useToggle |
| 状态机 | toggleMachine |
| 皮肤 | @xihan-ui/styles/toggle.css |
Props
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
pressed | boolean | ||
defaultPressed | boolean | ||
disabled | boolean | ||
variant | ActionVariant | 变体:solid / subtle / outline / ghost,默认 subtle(缺省中性淡底)。 solid 只在按下(on)时才是品牌实心,未按下时按 ghost 取面;其余三档按下时一律品牌淡底。 | |
tone | Tone | 颜色:brand / neutral / success / warning / danger / info。 | |
size | Size | 尺寸:sm / md / lg | |
iconOnly | boolean | 仅图标:左右内边距清零、宽高相等。宽度跟随当前尺寸档的高度, 不必把档位写进行内样式。图标按钮没有可见文字,作者须自行提供可及名。 | |
fullWidth | boolean | 撑满行宽:工具条中的一列开关常用。 | |
onPressedChange | (details: TogglePressedChangeDetails) => void | pressed 变化意图回调;受控时是唯一出口,非受控时随内部转移一并通知。 |
事件
自定义元素将载荷放在 detail;Vue 使用同名 emit。
| 事件 | 载荷 | 说明 |
|---|---|---|
pressed-change | TogglePressedChangeDetails | pressed 状态变化;detail 为 { pressed: boolean } |
React 适配器 props
只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。
| React 组件 | 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
XhToggle | children | ReactNode |
状态
公开状态写入 data-state。
| 部件 | 取值 |
|---|---|
root | 'on' | 'off' |
以下名称仅用于内部状态机。
状态:off · on
事件:TOGGLE · CONTROLLED.ON · CONTROLLED.OFF · PRESS.START · PRESS.END
判据:isPressedControlled · canPress
connect API
getXxxProps() 返回对应部件的宿主属性。
| 成员 | 类型 | 说明 |
|---|---|---|
pressed | boolean | |
setPressed | (next: boolean) => void | |
getRootProps | () => T['button'] |
无障碍
键盘
规格出处:W3C APG
| 按键 | 生效条件 | 行为 |
|---|---|---|
Space / Enter | focus in root, not disabled | 切换 pressed 状态 |
Space / Enter | held in root, not disabled | 按住期间投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下 |
ARIA
以下属性由 connect 生成。
| 部件 | 属性 | 值 |
|---|---|---|
root | aria-pressed | 'true' | 'false' |
样式参考
皮肤
@xihan-ui/styles/toggle.css 使用 [data-scope="toggle"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides。
数据属性
由 connect 生成;条件不成立时不输出无值属性。
| 部件 | 属性 | 值 |
|---|---|---|
root | data-disabled | ''(条件成立时才出现) |
root | data-full-width | ''(条件成立时才出现) |
root | data-icon-only | ''(条件成立时才出现) |
root | data-pressed | ''(条件成立时才出现) |
root | data-size | props.size |
root | data-state | 'on' | 'off' |
root | data-tone | props.tone |
root | data-variant | props.variant |
root | data-xh-action-control | '' |
root | data-xh-action-display | 'always' |
root | data-xh-action-profile | 'icon' | 'text' |
root | data-xh-action-size | props.size |
root | data-xh-action-variant | 'solid' | 'ghost' | props.variant |
root | data-xh-ink-surface | ''(条件成立时才出现) |
CSS 变量
本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。
| 变量 | 部件 | CSS 属性 | 状态 | 默认来源 | 说明 |
|---|---|---|---|---|---|
--xh-toggle-bg | root | --xh-ink-surfacebackground-color | defaultfocus-visiblexh-ink-surface | --xh-_action-variant-bg-focus-visible--xh-_action-variant-bg-rest | toggle 的 root 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-toggle-bg-active | root | background-color | disabledis(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_action-variant-bg-pressed | toggle 的 root 部件 background-color 覆盖槽。 |
--xh-toggle-bg-disabled | root | --xh-ink-surfacebackground-color | disabledxh-ink-surface | --xh-_action-variant-bg-disabled | toggle 的 root 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-toggle-bg-hover | root | background-color | disabledhoverloadingnot([data-disabled])not([data-loading]) | --xh-_action-variant-bg-hover | toggle 的 root 部件 background-color 覆盖槽。 |
--xh-toggle-bg-on | root | --xh-ink-surfacebackground-color | disabledfocus-visiblenot([data-variant='solid'])state=onvariant=solidxh-ink-surface | --xh-_tone-subtle | toggle 的 root 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-toggle-bg-on-active | root | background-color | disabledis(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])not([data-variant='solid'])pressedstate=onvariant=solid | --xh-_tone-subtle-active | toggle 的 root 部件 background-color 覆盖槽。 |
--xh-toggle-bg-on-disabled | root | --xh-ink-surfacebackground-color | disablednot([data-variant='solid'])state=onvariant=solidxh-ink-surface | --xh-_action-variant-bg-rest--xh-_toggle-bg-on | toggle 的 root 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-toggle-bg-on-hover | root | background-color | disabledhoverloadingnot([data-disabled])not([data-loading])not([data-variant='solid'])state=onvariant=solid | --xh-_tone-subtle-hover | toggle 的 root 部件 background-color 覆盖槽。 |
--xh-toggle-border | root | borderborder-color | defaultdisabledfocus-visiblehoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_action-variant-border-focus-visible--xh-_action-variant-border-hover--xh-_action-variant-border-pressed--xh-_action-variant-border-rest | toggle 的 root 部件 border、border-color 覆盖槽。 |
--xh-toggle-border-disabled | root | border-color | disabled | --xh-_action-variant-border-disabled | toggle 的 root 部件 border-color 覆盖槽。 |
--xh-toggle-border-on | root | borderborder-color | disabledfocus-visiblehoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])not([data-variant='solid'])pressedstate=onvariant=outlinevariant=solid | --xh-_tone-border-controltransparent | toggle 的 root 部件 border、border-color 覆盖槽。 |
--xh-toggle-fg | root | color | defaultdisabledfocus-visiblehoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_action-variant-fg-focus-visible--xh-_action-variant-fg-hover--xh-_action-variant-fg-pressed--xh-_action-variant-fg-rest | toggle 的 root 部件 color 覆盖槽。 |
--xh-toggle-fg-disabled | root | color | disabled | --xh-_action-variant-fg-disabled | toggle 的 root 部件 color 覆盖槽。 |
--xh-toggle-fg-on | root | color | disabledfocus-visiblehoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])not([data-variant='solid'])pressedstate=onvariant=solid | --xh-_tone-fg | toggle 的 root 部件 color 覆盖槽。 |
--xh-toggle-fg-on-disabled | root | color | disablednot([data-variant='solid'])state=onvariant=solid | --xh-_action-variant-fg-rest--xh-_toggle-fg-on | toggle 的 root 部件 color 覆盖槽。 |
--xh-toggle-font-size | root | font-size | default | --xh-_action-profile-font-size | toggle 的 root 部件 font-size 覆盖槽。 |
--xh-toggle-font-weight | root | font-weight | default | --xh-text-label-weight | toggle 的 root 部件 font-weight 覆盖槽。 |
--xh-toggle-gap | root | gap | default | --xh-_action-profile-gap | toggle 的 root 部件 gap 覆盖槽。 |
--xh-toggle-h | root | block-sizeinline-size | defaultxh-action-profile=icon | --xh-_action-profile-visual-size | toggle 的 root 部件 block-size、inline-size 覆盖槽。 |
--xh-toggle-icon-size | *root | --xh-icon-sizeblock-sizeinline-size | default | --xh-_action-profile-glyph-size | toggle 的 *、root 部件 --xh-icon-size、block-size、inline-size 覆盖槽。 |
--xh-toggle-px | root | padding-inline | default | --xh-_action-profile-padding-inline | toggle 的 root 部件 padding-inline 覆盖槽。 |
--xh-toggle-radius | root | border-radius | default | --xh-shape-control | toggle 的 root 部件 border-radius 覆盖槽。 |
--xh-toggle-shadow | root | box-shadow | disabledfocus-visiblehoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressedstate=on | none | toggle 的 root 部件 box-shadow 覆盖槽。 |
动效
动效角色:按压 · 状态(见动效规范)。
本组件皮肤不含过渡与关键帧,也没有脚本驱动的动效:状态一变,外观立即到位。
RTL
皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。
