无障碍评审输出规范:基于 talebook 前端实践的可访问性审查报告(Findings / Verification / Verdict)写作指南

原创2026-10-03 10:02:591,366 阅读
文章标签:后端前端

无障碍评审输出规范:基于 talebook 前端实践的可访问性审查报告(Findings / Verification / Verdict)写作指南

本篇指南围绕仓库内 review-output.md 定义的可访问性(Accessibility / a11y)评审输出格式展开,完整讲解一份独立无障碍评审报告的两段式结构:按原则分组的 Findings 表格,以及 Verification 与 Verdict 收尾。文章同时结合 talebook 前端实际代码(Vue 组件中的 aria-label、role="status"/role="alert" 活动区、aria-invalid 错误状态、:focus-visible 焦点环等)展示评审结论应如何被引用、验证并形成最终裁决。读完本文,你将能按统一格式撰写、评审并裁决无障碍问题,让评审结果可以被团队、Agent 与自动化工具直接复用。

一、这份规范在解决什么问题

无障碍(Accessibility)审查最大的痛点不是"发现不了问题",而是问题如何被记录、分级、汇总并形成可执行的结论。talebook 仓库的 .agents/skills/better-accessibility/ 目录为前端界面的可访问性工程定义了完整工作流(见 SKILL.md),而其中的 review-output.md 单独定义了独立评审(standalone review)的输出格式。

这份规范明确了两件事:

  1. 格式归属:当由 better-interface(跨领域界面评审编排技能,见 SKILL.md)统筹时,评审格式、严重度、合并规则、数量上限与最终裁决都由 better-interface 拥有;better-accessibility 只负责提供领域证据与发现。而当进行一次独立(standalone)的无障碍评审时,本规范全面接管。
  2. 输出结构:独立评审报告严格分为两部分——Findings(发现)与 Verification and Verdict(验证与裁决)。

这套设计把"证据收集"与"格式裁决"解耦,既保证了单领域审查的专业深度,又避免了多技能合流时格式互相冲突。从仓库的 Agent 编排文件(.agents/skills/better-accessibility/agents/openai.yaml)可以看到该技能以独立 Agent 形式存在,负责产品界面的可访问性工程。

二、Findings:按原则分组的发现表

独立评审的第一部分是 Findings。规范要求:

  • 按原则分组:所有已确认的发现必须按可访问性原则(Principle)归类;
  • 统一表格结构:每个分组使用一张 Markdown 表格,列为 Severity、Location、Before、After、Why;
  • 禁止散行写法:绝不使用独立的 "Before:" / "After:" 行,一切证据都进入表格单元格;
  • 合并系统性问题:同一根因反复出现的系统性缺陷合并为一行,并在该行内列出所有受影响位置;
  • 省略无发现原则:没有任何发现的原则组直接省略,不保留空表格。

2.1 Severity:三档严重度

级别 判定标准
HIGH 阻止任务完成、对辅助技术隐藏内容,或造成系统性无障碍失败
MEDIUM 使某个交互对用户而言明显更困难
LOW 孤立的打磨问题(isolated polish)

这个三档刻度与 better-interface 的共享严重度一致(HIGH 还涵盖误导用户、数据丢失风险、系统性重复失败;MEDIUM 涵盖理解力/效率/适应性/一致性的实质性损害;LOW 仅限全量模式下收录的有限影响问题)。无障碍领域的 HIGH 触发条件包括:无访问名的交互控件、无可视焦点指示的可键盘聚焦控件、指针可达但键盘不可达的路径、无视 prefers-reduced-motion 的动效、320px 宽度或 200% 缩放下被裁剪/遮挡/不可达的内容、对比度不达标的正文、仅靠颜色传达的状态,以及无确认/撤销/特殊处理的破坏性操作(见 better-interface/SKILL.md 第 5 条)。

2.2 Location:证据定位

Location 列必须给出精确引用:

  • 有源码工件(artifact)时:path/to/file:line,即"文件路径:行号";
  • 没有源码工件时:引用确切的界面与组件(如"设置页-设备列表-删除按钮"),而不是模糊的页面描述。

这一要求与 better-interface 的"证据优先"原则(Require Evidence)呼应:每一条发现都必须能追溯到具体的实现位置,禁止仅凭视觉观感或仅凭源码推测下结论。

2.3 Before / After:现状与可执行替代方案

  • Before:展示当前实现(真实代码片段);
  • After:给出可操作(actionable)的替换写法。

规范强调 After 必须是"可执行的修复",例如补上 aria-label="Close" 并把图标标记为 aria-hidden="true",而不是一句抽象的"提升可访问性"。同时,修复必须使用项目自身的风格体系(the project's own idiom),talebook 是 Vue + 组合式 API + 内联样式/Vuetify 生态,修复建议就应落在该技术栈上,而不是引入第二套样式系统(见 SKILL.md 引言)。

2.4 Why:指明违反的原则与用户影响

Why 列回答两个问题:违反了哪条可访问性原则?对真实用户(键盘用户、屏幕阅读器用户、低视力用户、触屏用户)产生了什么影响?

三、规范自带的四组示例:原则的落地形态

review-output.md 给出了四组完整示例,这四组恰好对应 SKILL 中的四条核心原则,是评审报告中最常见的四类发现。

3.1 Accessible names everywhere(访问名无处不在)

Severity Location Before After Why
HIGH src/Dialog.tsx:42 <button><XIcon /></button> Add aria-label="Close"; mark the icon aria-hidden="true" The icon-only control has no accessible name
HIGH src/Nav.tsx:18 <a href="/settings"><GearIcon /></a> Add aria-label="Settings" The link destination is unavailable to screen readers

图标独占的按钮/链接没有可访问名,屏幕阅读器只会读到空洞的"button"。修复要点:aria-label 给出名字,装饰性图标用 aria-hidden="true" 从无障碍树中剔除(绝不能加在可获得焦点的元素上,见 semantics-and-aria.md)。

3.2 Visible focus rings(可见焦点环)

Severity Location Before After Why
HIGH src/button.css:12 button:focus { outline: none; } button:focus-visible { outline: 2px solid; outline-offset: 2px; } Keyboard users cannot see focus
HIGH src/Menu.tsx:31 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 Menu navigation has no visible focus indicator

焦点环应使用 :focus-visible 而非裸 :focus——键盘与辅助技术聚焦时显示,鼠标点击时通常不显示,避免视觉噪音。绝不写 outline: none 而没有可见替代(见 focus-and-keyboard.md)。

3.3 Errors that announce(可播报的错误)

Severity Location Before After Why
HIGH src/EmailField.tsx:27 Error shown only as border-red-500 Add aria-invalid="true" + aria-describedby="email-error" with inline error text Color alone neither explains nor announces the error
MEDIUM src/SignupForm.tsx:64 Submit disabled until the form is valid Keep submit enabled; on failure, focus the first invalid field A disabled action hides what must be fixed

错误不能只靠颜色传达:失败字段加 aria-invalid="true",用 aria-describedby 指向行内错误文本,错误信息跟随字段被屏幕阅读器播报;提交按钮保持可用,在提交时校验并把焦点移到第一个无效字段(详见 forms.md)。

3.4 Minimum hit area(最小点击区域)

Severity Location Before After Why
MEDIUM src/Toolbar.tsx:22 size-4 icon-only button Extend the hit area to 44×44px with after:absolute after:size-11 The target is too small for reliable touch input

触屏目标过小导致误触。WCAG 2.5.8(AA)硬性底线是 24×24 CSS 像素,触屏上下文推荐 44×44px,桌面推荐 40×40px;可见元素可以保持小尺寸,通过伪元素扩展命中区域,且扩展区域不得与其他交互元素重叠(见 hit-areas.md)。

四、源码证据:talebook 前端的无障碍实现对照

规范要求评审的 Location 引用 path/to/file:line,而 talebook 的 Vue 组件中恰好存在大量可被评审引用的真实实现。以下是从 app/components 提取的实现事实,可作为"合格实现"的正面样本,也可作为评审定位格式的练习素材。

4.1 访问名:从 i18n 取值的 aria-label

图标按钮普遍使用 :aria-label 提供访问名,且文案来自 i18n 键(talebook 的中英文案见 app/i18n/locales/zh-CN.json 与 en-US.json):

  • AnnotationPanel.vue:刷新按钮 :aria-label="t('annotations.refresh')";
  • AudioJobsPage.vue:刷新 t('common.refresh');L114 打开书籍任务按钮 t('audiobook.openBookJob', { title: job.book.title });L351 关闭按钮 t('common.close');
  • AudiobookPlayer.vue:播放/暂停按钮的访问名随状态切换 player.playing ? t('audiobook.pause') : t('audiobook.play')。

其中 AudioJobsPage.vue:114 把书名动态拼进访问名("打开书籍任务《xxx》"),正是"可访问名应描述操作与对象"的良好实践——评审中若发现类似的动态语义,应判定为合格而非误报。

4.2 活动区(live region):role="status" 与 role="alert"

动态内容更新需要播报机制。规范与 screen-readers.md 给出的选择顺序是:焦点本身移动 → aria-describedby 绑定字段 → 非紧急用 role="status"(polite)→ 紧急用 role="alert"(assertive)。talebook 组件中两者皆有:

  • 加载/状态播报:AnnotationPanel.vue:91 <div role="status" aria-live="polite">、AuthorAliasPanel.vue:9、MetaList.vue:20 与 LibraryChipFilter.vue:69/164 的 role="status";
  • 紧急错误播报:BrsAccountSettings.vue:108、LibraryChipFilter.vue:129、MetaList.vue:35 的 role="alert";
  • PluginCapabilityTester.vue:101 也使用了 role="status"。

评审时可对照检查:常规 toast 或结果计数用 polite(role="status"),只有表单级/页面级紧急错误才允许 assertive(role="alert"),滥用 assertive 是常见失误(见 SKILL.md Common Mistakes)。

4.3 表单错误状态:aria-invalid + 行内错误

BrsAccountSettings.vue 是表单错误处理的完整样本:多个字段按校验结果动态绑定 :aria-invalid="Boolean(fieldErrors.endpoint)"(L43、L58、L73、L88),配合 role="alert" 区域播报表单级错误。这正符合"错误必须可播报、不能只靠颜色"的规范要求——评审报告中的 aria-invalid 与 aria-describedby 建议,在该组件中已有对应实现可参照。

4.4 焦点环:组件内 :focus-visible 样式

AudioJobsPage.vue 的 .job-plan-toggle:focus-visible { outline: 3px solid rgba(217,154,43,.42); outline-offset: 4px; } 与 LibraryChipFilter.vue 的 .library-filter-control:focus-visible 均使用 :focus-visible 而非裸 :focus,且自定义环带显式颜色与偏移——符合"优先保留浏览器环,自定义环必须验证与相邻颜色的对比"的原则(见 focus-and-keyboard.md)。

需要说明:以上仅是从源码结构可确认的实现事实。它们不代表这些组件通过了完整评审;按规范第 8 条(Verify What Can Be Verified),最终裁决必须基于真实运行的检查(键盘走查、可访问名检查、屏幕阅读器测试)而非代码阅读。

五、Verification and Verdict:验证与裁决

Findings 之后是报告的第二部分,包含两个强制步骤:

5.1 Verification(验证)

列出实际执行过的检查及其观察结果,包括:

  • 键盘遍历(keyboard traversal):每个流程能否脱离鼠标完成;
  • 可访问名检查(accessible-name inspection):每个交互控件是否播报名称、角色与状态;
  • 屏幕阅读器或自动化检查(screen-reader / automated checks):适用时记录工具与结果;
  • 诚实标注未验证项:如果某项检查没有运行,必须明确写出"仍需要验证什么",而不是默认通过。

这与 SKILL 的评审方法论一致——"先用纯键盘走完整条流程,再以屏幕阅读器用户身份走查:每个控件是否播报名称、角色与状态"(见 SKILL.md)。评审只读不改,验证缺口永远不能转变成一条"发现"。

5.2 Verdict(裁决)

裁决只有三种,规则明确:

裁决 触发条件
Block 仍存在任意一条 HIGH 发现
Needs changes 仅剩 MEDIUM 或 LOW 发现
Approve 不再存在任何可操作(actionable)发现

5.3 零发现场景

当评审没有任何发现时:

  1. 省略所有表格(不保留空表);
  2. 直接声明 "No actionable accessibility findings";
  3. 报告验证过程与结果;
  4. 以 Approve 结尾。

六、与 better-interface 编排的关系:谁拥有格式与裁决

规范开头特别划清了职责边界,这是报告可被多技能复用而不冲突的关键:

  • 独立评审时:review-output.md 拥有格式、严重度、合并、上限与裁决;
  • 由 better-interface 统筹时:编排技能拥有格式、严重度、合并规则、发现上限与裁决,better-accessibility 只交付领域证据与发现(domain evidence and findings)。

better-interface 的编排规则进一步说明:当领域技能经由它加载时,要应用其原则与参考文档,但忽略其 Reporting 章节及其指向的 review-output.md,改用统一合并格式、共享严重度与上限;若该技能不可用,该领域标记为 Not reviewed 并写明缺失技能,不得用相邻技能顶替(见 better-interface/SKILL.md 第 3 条)。若评审范围来自版本控制(分支/PR/未提交改动),则属于 interface-review 的变更评审范畴,better-interface 不代行解析变更范围。

理解这层"编排者 vs 领域技能"的职责划分,能帮助你在实际工作流中正确选择输出模板:单领域深度审查用本规范的两段式独立报告;跨领域综合评审用 better-interface 的合并报告(含 Scope and Coverage、Considered but Rejected、Verification、Verdict 与变更评审扩展节)。

七、实操清单:按本规范产出一份评审报告

  1. 确定评审主体:确认是独立无障碍评审(用本格式)还是 better-interface 统筹(移交编排)。
  2. 按原则分组:参考 SKILL.md 的 Quick Reference 确定检查维度——Focus & Keyboard、Semantics & ARIA、Forms、Screen Readers、Hit Areas、Motion & Zoom。
  3. 收集证据:逐条确认发现,Location 必须精确到 path/to/file:line;无源码时引用确切界面与组件。
  4. 合并系统性问题:同一根因的多处位置合并为一行,全部列出。
  5. 判定严重度:对照 HIGH/MEDIUM/LOW 定义;better-interface 的触发清单一旦命中即 HIGH。
  6. 补齐 Verification:记录真实执行的检查与观察结果,诚实标注未验证项。
  7. 给出唯一裁决:Block / Needs changes / Approve,与剩余发现的严重度严格对应。

按照这套流程产出的报告,每一条发现都具备"原则 + 位置 + 现状 + 替代方案 + 影响"的完整证据链,验证过程可复现,裁决规则无歧义——这正是无障碍评审从"主观意见"走向"可审查、可引用、可执行"的关键。

相关文档索引

登录后查看全文
talebook