指南

可访问性

Liquid Glass 组件的标签、键盘行为、焦点管理与实时区域支持。

可访问性内置于行为层,而不是玻璃样式。交互组件提供角色、状态、键盘交互、 焦点管理与原生表单集成。视觉层只改变表面。

本指南说明组件库已经保证的行为,以及应用仍然需要自行决定的部分。

为每个控件命名

组件可访问名称来源
InputField 标签,或 aria-label / aria-labelledby
Checkboxlabel,或 aria-label / aria-labelledby
CheckboxGrouplabel,或 aria-label / aria-labelledby;每个选项使用自己的 label
Switchlabel,或 aria-label / aria-labelledby
RadioGrouplabel,或 aria-label / aria-labelledby
Selectlabel,或 aria-label / aria-labelledby
Slideraria-label / aria-labelledby,或每个 thumb 的 getAriaLabel
Progresslabel,或 aria-label / aria-labelledby
Tabs标签栏上的 aria-label / aria-labelledby
Togglelabel,或 aria-label / aria-labelledby
ToggleGrouparia-label / aria-labelledby
ScrollAreaviewport 上的 aria-label / aria-labelledby
Menu触发器标签;纯图标触发器使用 aria-label / aria-labelledby
Tooltip触发器标签;提示内容仅作补充
Dialog、AlertDialog、Drawer必填的 title 属性
Popover必填的 title 属性

Fieldset 通过 legend 为一组相关字段提供共享的可访问名称;组内控件仍需各自的标签。

优先使用可见标签。标签渲染在组件外部也可以,只要正确关联:

<span id="volume-label" className="text-sm text-ui-ink">
  音量
</span>
<Slider aria-labelledby="volume-label" defaultValue={40} />

区间滑块请传入 getAriaLabel,让每个 thumb 都有不同的名称:

<Slider
  aria-label="价格区间"
  defaultValue={[20, 80]}
  getAriaLabel={(index) => (index === 0 ? "最低价格" : "最高价格")}
/>
Receive notificationsWhen enabled, new messages are sent to your inbox.

Switch 与 Checkbox 使用可见标签作为可访问名称,并通过 aria-describedby 关联描述。CheckboxGroup 分别为分组与每个选项命名; Tab 在其复选框之间移动。Button、Input 等组件内部的装饰性图标都标记了 aria-hidden="true"。

键盘行为

组件遵循以下原生交互模式:

交互预期行为
Tab / Shift+Tab在控件之间移动焦点
Enter / Space激活按钮、Toggle、Checkbox、Switch、标签页、菜单项与选择器选项
方向键移动 Slider thumb、在 Toggle Group 与标签页中导航,以及在菜单项或选择器选项之间移动
Escape关闭 Dialog、Alert Dialog、Drawer、Popover、Menu、Select 或 Tooltip
Home / End将单值 Slider 移到边界值(区间 thumb 会移到相邻 thumb 的边界),或跳到第一个或最后一个标签页
Page Up / Page Down按 largeStep 移动 Slider
Typeahead在 Menu 或 Select 中匹配标签

Accordion 触发器使用真实按钮并暴露 aria-expanded,遵循文档的 Tab 顺序。 loopFocus 与 orientation 已废弃,不再影响键盘焦点。Toggle Group 支持单选与 多选,并具备预期的方向键 roving focus。Tabs 在标签栏内使用 roving focus:方向键 跟随布局方向,Home 与 End 跳到首尾,Enter 或 Space 激活当前焦点标签。 设置 activateOnFocus 后,焦点移动时会直接切换面板。Scroll Area 保留原生滚轮、 触控板与键盘滚动;自定义滚动条是装饰性的,对辅助技术隐藏。

Menu 与 Select 在浮层内使用 roving focus:方向键在启用的条目之间移动, typeahead 匹配标签,Escape 把焦点返回触发器。 禁用的条目仍会被播报,但无法激活。Tooltip 在悬停或键盘聚焦时打开,在失焦或 Escape 时关闭;它仅作视觉提示,不会被播报为描述,因此纯图标触发器仍需自己的 可访问名称。

浮层与焦点

Dialog、AlertDialog 与 Drawer 是模态的:

  • 打开时焦点移动到弹窗内。
  • 打开期间 Tab 被限制在弹窗内。
  • Escape 会关闭这三种浮层。点击背景还会关闭 Dialog 与 Drawer(除非禁用),AlertDialog 则始终禁止点击背景关闭。
  • 关闭后焦点返回触发器。
  • 打开期间锁定页面滚动。

Popover 有意保持非模态:焦点不会被限制,页面仍可滚动,点击外部或按 Escape 会关闭。它适合紧凑设置、筛选器与上下文操作,不适合需要用户全神贯注的 多步流程。

Menu 与 Select 默认是模态的:浮层打开时外部交互被锁定,Escape 会关闭浮层 并把焦点返回触发器。只有周围页面必须保持可交互时才设置 modal={false}。

AlertDialog 用于破坏性或不可逆决定。当用户必须在明确操作之间选择时,应使用 它而不是普通 Dialog。

Toast 与实时区域

ToastProvider 渲染带实时区域语义的 toast viewport。在应用根部保留 一个 provider,并把 <Toast /> 放在应用内容之后,确保 viewport 可用。

  • 用 type 添加状态图标:info、success、warning、error 或 loading。
  • 保存失败等需要立即播报的消息使用 priority: "high"。
  • 消息保持简短、可操作。不要把焦点移到 toast 上。
  • 用户可以撤销或重试时,通过 actionProps 提供操作。
  • timeout 要足够阅读;需要用户操作时设为 timeout: 0。

toast.promise 会先显示 loading,再在原 toast 上更新成功或失败状态,避免重复 播报。

动效与对比度

所有装饰性过渡都包含 motion-reduce 变体。用户设置 prefers-reduced-motion: reduce 时,布局与状态变化仍然保留,但动效会被移除或 缩短。

玻璃表面是半透明的。请在实际背景上检查文字对比度,尤其是图片、渐变与信息密集的 仪表盘。页面需要更强的共享遮罩时,可以用可选的 玻璃预设插件切换到 data-glass="thick",无需 修改组件代码。默认黑白配色面向安静的界面;自定义 token 时,应在明暗两套主题中 维持相同的对比关系。

测试清单

  • 不用鼠标,只用 Tab 走完页面,确认每个控件都能到达。
  • 关闭 Dialog 或 Drawer 后,确认焦点返回触发器。
  • 用屏幕阅读器阅读表单:名称、描述与错误应只播报一次,并且上下文正确。
  • 确认 Switch 与 Checkbox 会播报选中状态。
  • 确认 CheckboxGroup 会分别播报分组名称与每个选项。
  • 确认区间滑块会播报两个 thumb 的值与名称。
  • 用键盘打开 Menu 与 Select,确认方向键、typeahead 与 Escape 行为正确。
  • 聚焦纯图标 Tooltip 触发器,确认其可访问名称。
  • 触发 Toast,确认消息被播报且不会抢走焦点。
  • 开启减少动效与高对比度主题分别测试页面。
  • 用真实内容测试;占位文本经常会掩盖标签问题。

可访问性是共同责任。组件提供交互基础,但页面标题、错误信息、页面结构与内容仍然 属于你的应用。

相关组件