无障碍
Tuffex 组件遵循的四条约定,以及覆盖到哪里为止
范围
Tuffex 以 WCAG 2.1 AA 为目标。这是组件开发时对齐的标准,不是认证结论——本页描述组件实际遵循的约定,并明确说明哪些地方覆盖仍不完整。
焦点
焦点环画在 :focus-visible 上,而不是 :focus:鼠标点击之后不会留下一圈残留,键盘走查则始终能看见。焦点环本身由两个 token 定义,而不是写死的 outline:
| Token | 作用 |
|---|---|
--tx-focus-ring-color | 焦点环自身颜色 |
--tx-focus-ring-shadow | 环外的光晕 |
深色与高对比度调色板都会重新定义这两个值,所以底色变化时焦点环依然可见。约五十个组件样式表写了显式的 :focus-visible 规则;其余组件要么不可聚焦,要么把焦点交给了可聚焦的子元素。
被圆角容器裁切的组件把焦点环画在内侧而不是外侧——浏览器自带的 outline 落在元素之外,会被父级的 overflow: hidden 切成直角。折叠面板的表头就是这个处理的样板。
动效
每个动画都应当响应 prefers-reduced-motion: reduce,目前约六十个组件样式表带了这一段。约定是保留状态、去掉位移:不确定态进度条不再来回扫动,但仍是一条半透明填充的轨道,依然读作「进行中」;折叠面板直接展开,不做缓动。
动画只用合成属性——transform 与 opacity。确实必须动布局时(CSS 无法在 0 与 auto 之间补间高度),组件会先测量再用 JavaScript 驱动数值,而不是拿一个猜的固定高度去动 height。
对比度
除默认调色板外,Tuffex 还带一套高对比度配色,在浅色与深色下都提高文本与边框对比度。它通过 @media (prefers-contrast: more) 自动跟随系统偏好,应用也可以强制开启或退出——选择器见《主题定制》。
对比度被当作可复核的属性而不是凭感觉:容易出错的 token 组合(同色 tint 上的浅色徽标、深色页面上的版本胶囊)会把实测比值写在声明旁边的注释里。
语义
约九成组件设置了显式的 role 或 ARIA 属性。反复出现的几种模式:
- 用自身文本命名。 组件的可访问名来自它可见的标签。当某个控件只能靠「在它上面印一行字」才有名字时(比如进度条),组件提供
ariaLabelprop,让命名不必变成可见文案。 - 装饰部分被隐藏。 与相邻文本重复的字形和装饰带
aria-hidden,屏幕阅读器只念一遍标签而不是两遍。 - 展开状态被连起来。 可展开的行在触发器上写
aria-expanded,并用aria-controls指向面板生成的 id。
覆盖到哪里为止
- 没有自动化的无障碍测试套件。 包级别的横向测试覆盖的是套件入口与全局安装路径;无障碍行为由各组件自己的测试和人工评审保证,因此可能有遗漏。
- 上面这些约定是「大多数」组件遵循,不是全部。侧边栏里仍标着
开发中的组件文档,对应的组件尚未过评审。 - 屏幕阅读器测试目前是人工进行的,还没有固定的测试矩阵。
发现问题时,对应组件的文档页里有源码位置——改在那里,所有使用方一次性受益。
源码
- 焦点与对比度 token:
packages/tuffex/packages/components/style/variables.scss。 - 主题与对比度选择器:《主题定制》。