diff --git a/docs/specs/2026-10-01-p9b-a11y-keyboard-design.md b/docs/specs/2026-10-01-p9b-a11y-keyboard-design.md index 75b5a98..ad6eafa 100644 --- a/docs/specs/2026-10-01-p9b-a11y-keyboard-design.md +++ b/docs/specs/2026-10-01-p9b-a11y-keyboard-design.md @@ -23,7 +23,7 @@ 1. `--color-success: #2fa46a` 对 paper 仅 **2.83**,对 surface 3.16 —— 作为成功 toast 的底色配 `text-paper`(12px 粗体,非大字号)实测 **3.16**,AA 正文需 4.5,**FAIL**。 2. 错误 toast 用 `bg-accent`(#e8552f)配 `text-paper` 实测 **3.64**,**FAIL**(AA 正文需 4.5)。 -3. 三个管理视图共 **19 个 `` 零 `scope`**,且两个「操作」列的表头是空 ``(无可访问名);全仓 `scope="row"` 出现 0 次。屏幕阅读器读表格时无法把单元格与列头关联。 +3. 三个管理视图共 **24 个 `` 元素零 `scope`**(`grep -c '` 塞在同一 `` 行内,故行数 < 元素数;以词界 ``(无可访问名);全仓 `scope="row"` 出现 0 次。屏幕阅读器读表格时无法把单元格与列头关联。 4. 五星评分按钮的可访问名就是字形本身「★」/「☆」——读屏逐个念「星 星 星」,无法知道这是几分、当前评了几分、点了会怎样。 5. 全站**无 skip-link**:键盘用户每个页面都要 Tab 过页头(logo + 3 条导航 + 贴纸 + 登录/用户菜单 4 项)才能到正文。 6. SPA 导航后**无焦点管理**:`router` 的 `afterEach` 只设 title/description,焦点留在旧位置(通常是 body),读屏用户点链接后听不到任何新页面上下文。 @@ -38,7 +38,7 @@ | D-C | 对比度守卫测试 | 新增 `app/lib/contrast.test.ts`:解析 `main.css` 的 `@theme` 令牌,按 WCAG 2.1 相对亮度算比值,钉死关键配色对 ≥4.5(焦点环 ≥3) | 仿既有 `app/lib/no-gradient.test.ts` 的源码级守卫范式,让「不许再引入低对比配色」成为可执行约束而非口头纪律。放弃逐组件视觉回归:成本高且测不到令牌层。 | | D-D | skip-link | `App.vue` 根 div 首子元素插 ``;`
`;样式走 Tailwind `sr-only` + `focus:not-sr-only` 组合,**不新增 CSS 规则** | 原生锚点跳转会同时移动焦点(href 指向带 tabindex=-1 的 main),无需 JS。`focus:z-[80]` 压过 toast 的 `z-[70]`。放弃自绘 `.skip-link` CSS:工具类已足够,少一处需维护的样式。 | | D-E | 路由后焦点管理 | `attachTitleHook` 的 `afterEach` 改为 `(to, from)`,当 `to.path !== from.path` 时对 `#main` 调 `focus({ preventScroll: true })`;`#main` 不存在时静默 no-op | 只在**路径**变化时移焦:`/games → /games?tag=数字`(P10 T3 的标签点击)属同页筛选,抢焦点会打断用户;路径变化才是真正的「换页」。`preventScroll` 因为 `scrollBehavior` 已负责滚动,双重滚动会抖。放弃聚焦各页 h1:17 个视图有 2 个含双 h1(GameView / OutboundView 的 notFound 分支),聚焦目标不唯一,且 h1 加 tabindex 会污染 Tab 序。 | -| D-F | 表格列头语义 | 三个管理视图全部 `` 加 `scope="col"`;两个空的操作列表头改为 `操作` | `scope="col"` 是最小且正确的修复。**不**改 `` → ``:那要把每行首格的排版结构(含 `` 嵌套、font-bold 混排)重写成表头单元格,视觉回归风险大而收益有限(列头关联已解决读屏的主要痛点)。空表头补 sr-only 文本,否则操作列在读屏里是「无名第 5 列」。 | +| D-F | 表格列头语义 | 三个管理视图全部 `` 加 `scope="col"`(元素级 24 个:AdminView 13 + AdminUsersView 6 + AdminAuditView 5);两个空的操作列表头改为 `操作` | `scope="col"` 是最小且正确的修复。**不**改 `` → ``:那要把每行首格的排版结构(含 `` 嵌套、font-bold 混排)重写成表头单元格,视觉回归风险大而收益有限(列头关联已解决读屏的主要痛点)。空表头补 sr-only 文本,否则操作列在读屏里是「无名第 5 列」。 | | D-G | 表格守卫测试 | 新增 `app/lib/tableScope.test.ts`:扫描 `app/**/*.vue`,断言每个 ``;每颗星 `:aria-label="\`评 ${i} 星\`"`,内层字形 `