无障碍
thl-ui 以 WCAG 2.1 AA 为目标。三个 playground 的每个页面(75 个路由 × React / Vue / Angular,浅色和暗色模式)都使用 axe-core 进行审查,没有任何 serious 或 critical 级别的问题。
sh
node scripts/a11y.mjs http://localhost:5181 # React,遇到 serious/critical 即失败
node scripts/a11y.mjs http://localhost:5182 --dark # Vue,暗色模式
node scripts/a11y.mjs http://localhost:5183 --min moderate --json report.json组件为你做了什么
| 方面 | 行为 |
|---|---|
| 颜色 | 每一组文字/背景的对比度均 ≥ 4.5:1(见 无障碍配色对);亮色填充使用深色文字 |
| 表单 | Field 会为你放入的任何控件关联 <label for>、aria-describedby(帮助 / 错误)和 aria-invalid,自定义控件则通过 aria-labelledby 关联。错误使用 role="alert" 并且已翻译 |
| Checkbox / Switch | 使用原生 input,因此支持键盘和表单。标签文字即为无障碍名称;仅有图标时可使用 ariaLabel |
| Select | Combobox 模式:role=combobox + listbox、aria-activedescendant、方向键 / Enter / Esc、输入即搜索 |
| 日期 / 时间选择器 | 触发器是带 aria-haspopup="dialog" 和 aria-expanded 的 combobox;日历网格带有完整日期的 aria-label |
| Slider | role=slider,带 value / min / max / valuetext;方向键、Home / End、PageUp / PageDown;范围滑块的两个手柄分别命名为 "Minimum" / "Maximum" |
| Tabs | Roving tabindex,方向键会跳过禁用的标签页,Home / End,aria-controls / aria-labelledby |
| Modal / Drawer | aria-modal、焦点陷阱、焦点恢复、Esc、滚动锁定;关闭的抽屉为 inert |
| Dropdown / Popover | aria-haspopup / aria-expanded / aria-controls 设置在你的触发元素上,而不是包裹元素;Esc 会归还焦点 |
| Tooltip | 在悬停和聚焦时显示,通过 aria-describedby 关联 |
| Progress | role=progressbar,带数值和本地化名称 |
| 布局 | 跳转链接(skip link)、header / nav / main / footer 地标、侧边菜单中的 aria-current="page"、h1 页面标题 |
| 动效与 RTL | 使用 CSS 逻辑属性,因此 dir="rtl" 会镜像布局;:focus-visible 焦点环使用主题色 |
你需要负责的部分
- 为仅图标按钮添加
aria-label:<ThlButton circle icon="heart" aria-label="Like" />。 - 将控件放入带
label的Field中,或为它们添加aria-label。 - 自行构建的可滚动区域需要
tabindex="0"和标签。 - 自定义颜色:保持文字对比度 ≥ 4.5:1。同时覆盖
--thl-color-x以及--thl-on-x/--thl-color-x-text。