# 无障碍

让所有人都能顺畅使用界面，是组件库的基础设计原则。无论是用键盘操作，还是依赖读屏软件（屏幕阅读器），都能正常使用。组件与示例不会为了好看而去掉焦点环，也不会为了极简而降低色彩对比度。

## 键盘焦点指示

键盘操作时，焦点外边框是告诉用户「我当前聚焦在哪」的关键向导。组件库统一采用 `--astryx-focus-outline-*` 变量来管理焦点外观：宽度固定为 2px，实线样式，颜色采用主题强调色 `--astryx-color-accent`，并保持 3px 的向外间距。

不要在全局样式中写 `outline: none`。文档站只在自带内部圆角焦点效果的控件（如特定输入框）上，略微调整外轮廓，避免出现双层边框。

## 给无文字的按钮起名字

如果一个按钮只有图标没有文字，读屏软件就无法知道它是做什么的。因此，纯图标按钮必须提供可访问名称（Accessible Name）：

- `IconButton` 组件的 `label` 属性是必填的，它会直接作为无障碍名称念给读屏用户听。
- `NavItem` 的 `label` 同样必填。
- 纯装饰性的图形应当使用 `aria-hidden="true"` 隐藏，不要试图直接用图标类名充当文字内容。

如果你需要让某些说明文字能够被读屏软件听到、但又不想在视觉界面上占用版面，可以使用 `@astryx-vue/core/VisuallyHidden` 提供的 `VisuallyHidden` 组件。

## 浮层与弹窗处理

弹窗和下拉浮层需要精细的无障碍焦点流转管理：

- **限制焦点**：使用 `useFocusTrap` 把键盘 Tab 切换限制在弹窗内，防止焦点跳到背后的主页面上。
- **还原焦点**：使用 `useRestoreFocus`，在弹窗关闭后，自动把焦点送回到刚才点击打开它的那个按钮上。
- **便捷关闭**：浮层的按下 Escape 键退出逻辑统一交给 `useDismiss` 的撤销栈管理，按由内向外的顺序逐层关闭。
- **锁定滚动**：浮层打开时，通过 `useScrollLock` 锁定背景的滚动，避免误触。

## 读屏播报与 AI 对话交互

- **主动通知**：某些操作完成后（比如点击复制按钮成功），如果界面只变化了按钮文字，读屏软件往往不会自动读取。此时可以通过 `useAnnounce` 触发语音播报；`useClipboard` 函数也支持传入 `announce` 参数，写入剪贴板成功后会主动提醒读者。
- **键盘导航**：列表和菜单的上下左右方向键切换，分别封装在 `useListFocus`、`useGridRovingFocus` 和 `useTypeahead`（字母快速跳转匹配）组合式函数中。
- **AI 流式输出**：`ChatMessageList` 的底层角色被标记为 `role="log"`。当 AI 助手的文本还在打字机式流式增长时，请保持 `isStreaming` 为 `true`，这样读屏软件会等到本轮打字停顿或完成后再朗读，不会每出来一个字都念一遍。

## 尊重减少动效设置

对于容易产生晕动反应的用户，组件库所有共享动画都严格遵循系统的 `prefers-reduced-motion` 设置。当用户开启「减少动效」时，大幅度的平移与缩放会自动降为 0，仅保留平滑的淡入淡出，具体细节可查看 [动画](/themes/motion)。

组件库的无障碍表现以各组件文档中的无障碍说明和代码库中的自动化测试为准。
