keyboard

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Keyboard

键盘

This skill puts the mouse away and walks a running page with keys alone. It records every focus stop in order and returns a numbered report of what the keyboard cannot reach, see or operate.
此 skill 收起鼠标,仅使用按键遍历正在运行的页面。它按顺序记录每个焦点停靠点,并返回一份带编号的报告,列出键盘无法到达、看见或操作的控件。

Every stop pressed, never read from the code

逐一按下每个停靠点,绝不读取代码推断

Focus order, reach and operation are judged from keys pressed in the running page. A stop the walk did not press is
Not verified
, never assumed. One unreachable control is a finding however minor the control.
How the focus ring looks, dialog focus traps and accessible names belong to
defaults
, and a failure there cites its id. Opening the running result belongs to
verify
. Forcing hidden states open belongs to
lab
.
焦点顺序、可达性和可操作性均根据在正在运行的页面中实际按下的按键来判断。遍历时未按下的停靠点一律标为
Not verified
,绝不做任何假设。任何不可达的控件,无论多么轻微,都算一个发现。
焦点环的外观、对话框焦点陷阱和可访问名称属于
defaults
,其中出现失败时应引用相应的 id。运行结果中的打开操作属于
verify
。强制打开隐藏状态属于
lab
。

1. Load the recorder

1. 加载记录器

Open the page at the state the user named and click nothing. Run tabstops.js through the browser's evaluate call. It returns pointer targets with no keyboard way in, then records each stop as keys are pressed. Judging order or reach from the markup is
keyboard-press-the-keys
.
Send keys through trusted input, such as Playwright's
keyboard.press
or the operating system. A dispatched DOM
KeyboardEvent
never moves focus, so a walk with no stops means the keys never arrived.
在用户指定的状态打开页面,不点击任何内容。通过浏览器的 evaluate 调用运行 tabstops.js。它先返回只能通过指针访问、无法通过键盘进入的目标,随后在按键过程中记录每一个停靠点。如果根据标记代码判断顺序或可达性,则属于
keyboard-press-the-keys
。
通过 trusted input 发送按键,例如使用 Playwright 的
keyboard.press
,或通过操作系统发送。派发的 DOM
KeyboardEvent
不会移动焦点,因此若一次遍历没有产生任何停靠点,就说明按键从未送达。

2. Walk forward, then back

2. 向前遍历,再向后遍历

Press Tab from the top of the page until focus leaves it, then Shift+Tab back to the start. Read
window.__keyboard.stops
and call
window.__keyboard.highlight()
.
Stops follow the reading order of the layout. A jump from the header to the footer and back, or any positive
tabindex
, is
keyboard-order-follows-layout
.
Every stop shows an indicator on screen. A stop with no visible ring is
keyboard-see-every-stop
. Focus landing on links inside a closed drawer is
keyboard-no-hidden-stops
. A stop with no name cites
defaults-name-icon-buttons
.
When navigation comes before the main content, the first stop is a skip link to it. Twenty header stops before the first result is
keyboard-skip-link
.
从页面顶部按 Tab,直到焦点移出页面,再按 Shift+Tab 返回起点。读取
window.__keyboard.stops
并调用
window.__keyboard.highlight()
。
停靠点应遵循布局的阅读顺序。从页眉跳到页脚再返回,或存在任何正数
tabindex
,均属于
keyboard-order-follows-layout
。
每个停靠点都会在屏幕上显示指示标记。没有可见焦点环的停靠点属于
keyboard-see-every-stop
。焦点落在已关闭抽屉内的链接上属于
keyboard-no-hidden-stops
。停靠点没有名称时,引用
defaults-name-icon-buttons
。
当导航位于主要内容之前时,第一个停靠点应是通往主要内容的 skip link。在找到第一个结果之前出现二十个页眉停靠点,属于
keyboard-skip-link
。

3. Reach every control

3. 到达每一个控件

Compare the stops against what the page shows and against the recorder's
unreachable
list. A clickable
div
the walk never lands on is
keyboard-reach-every-control
.
将停靠点同页面显示的内容及记录器的
unreachable
列表进行对比。遍历从未落在某个可点击
div
上,属于
keyboard-reach-every-control
。

4. Operate each control

4. 操作每一个控件

Enter and Space press buttons, Enter follows links and Space toggles checkboxes and switches. A control that answers a click but no key is
keyboard-operate-every-control
.
Menus, tabs, radio groups, listboxes and grids take one Tab stop, and arrows move inside them. A menu where every item is its own Tab stop is
keyboard-arrows-inside-composites
.
Escape closes the open menu, popover, sheet or dialog. An overlay that only a click can close is
keyboard-escape-closes
.
使用 Enter 和 Space 可激活按钮;Enter 可跟随链接,Space 可切换复选框和开关。控件响应点击,却不响应任何按键,属于
keyboard-operate-every-control
。
menu、tab、radio group、listbox 和 grid 等复合控件只占一个 Tab 停靠点,方向键用于在组件内部移动。如果 menu 中每个项目都是独立的 Tab 停靠点,属于
keyboard-arrows-inside-composites
。
按 Escape 可关闭已打开的 menu、popover、sheet 或 dialog。只能通过点击关闭的 overlay 属于
keyboard-escape-closes
。

5. Open and close each overlay

5. 打开并关闭每一个浮层

Open each dialog, menu and popover from the keyboard. Focus moves inside, stays inside a modal and returns to the trigger on close. A failure cites
defaults-trap-and-return-focus
.
使用键盘打开每一个 dialog、menu 和 popover。焦点移入内部,在 modal 中保持,并在关闭后返回触发元素(trigger)。任一失败均引用
defaults-trap-and-return-focus
。

6. Remove something, then find focus

6. 移除内容后,确认焦点位置

Delete a row, dismiss a toast, collapse a section and submit a form from the keyboard. Focus lands on a neighbour, the container or the result. A stop the recorder marks
lost
, with focus left on
body
, is
keyboard-focus-survives-removal
.
使用键盘删除一行、关闭 toast、折叠 section 并提交 form。焦点应落到相邻元素、容器或结果上。记录器将某个停靠点标记为
lost
,且焦点留在
body
上,属于
keyboard-focus-survives-removal
。

7. Report the walk

7. 报告遍历结果

Return the stops as a numbered list of role and name, with the screenshot showing the
highlight()
numbers. Cite each finding by its stop number and the key that failed. A finding with no stop and no key is
keyboard-numbered-walk
.
将停靠点以 role 和 name 组成的编号列表返回,并提供显示
highlight()
编号的截图。每个问题均引用其停靠点编号和未生效的按键。如果问题既无停靠点也无按键信息,则属于
keyboard-numbered-walk
。

The pair

成对对照

Every check is a pair. The broken line sits beside the line that replaces it.
RuleBrokenReplacement
keyboard-press-the-keys
"The markup uses buttons, so it is reachable"The walk recorded with Tab and Shift+Tab
keyboard-order-follows-layout
tabindex="3"
on the search field
No positive
tabindex
, the field placed in reading order
keyboard-see-every-stop
Stop 7 focused with no visible ringStop 7 showing the project's
:focus-visible
outline
keyboard-no-hidden-stops
Tab landing on links in the closed drawer
inert
on the drawer while it is closed
keyboard-skip-link
Twenty header stops before the first resultA
Skip to Content
link as stop 1
keyboard-reach-every-control
<div onClick={openRow}>
<button onClick={openRow}>
keyboard-operate-every-control
A switch that toggles on click onlySpace toggles it
keyboard-arrows-inside-composites
Eight Tab stops inside one menuOne stop, arrows move between items
keyboard-escape-closes
A popover that closes on outside click onlyEscape closes it and focus returns to the trigger
keyboard-focus-survives-removal
Focus on
body
after deleting a row
Focus on the next row
keyboard-numbered-walk
"Keyboard support is patchy""Stop 12, Space does nothing on
Notifications
"
每项检查都是成对对照:错误示例与替代方案并列。
规则错误示例替代方案
keyboard-press-the-keys
“标记使用了 button,因此它是可访问的”使用 Tab 和 Shift+Tab 记录的遍历结果
keyboard-order-follows-layout
tabindex="3"
位于搜索字段上
不使用正数
tabindex
,并按阅读顺序放置该字段
keyboard-see-every-stop
停靠点 7 获得焦点,但没有可见焦点环停靠点 7 显示项目的
:focus-visible
外轮廓
keyboard-no-hidden-stops
Tab 落在已关闭抽屉内的链接上抽屉关闭时设置
inert
keyboard-skip-link
在第一个结果之前有二十个页眉停靠点将
Skip to Content
链接作为停靠点 1
keyboard-reach-every-control
<div onClick={openRow}>
<button onClick={openRow}>
keyboard-operate-every-control
仅通过点击切换的开关使用 Space 切换
keyboard-arrows-inside-composites
一个菜单内有八个 Tab 停靠点仅有一个停靠点,使用方向键在项目之间移动
keyboard-escape-closes
只能通过点击页面外部关闭的 popoverEscape 关闭它,且焦点返回触发元素
keyboard-focus-survives-removal
删除一行后焦点位于
body
上
焦点位于下一行
keyboard-numbered-walk
“键盘支持不完善”“停靠点 12,Space 对
Notifications
不起作用”

Reporting

报告

Severity.
HIGH
is a control the keyboard cannot reach or operate, or focus lost to
body
after an action.
MEDIUM
is a stop out of reading order, a stop with no visible ring or a stop hidden off screen. It is also a composite with a Tab stop per item, or an overlay Escape does not close.
LOW
is a missing skip link, or a report without numbered stops.
Format. One finding per root cause, numbered and citing the stop:
1. file:line - [rule-id] stop N, key, what is wrong
Cite the recorder's element when the source line is not found. Then a
Rule | Count | Severity
summary.
Block
when any
HIGH
remains,
Approve
otherwise. Mark content inside cross-origin frames as
Not verified
.
严重性。
HIGH
是键盘无法到达或操作的控件,或者执行操作后焦点丢失到
body
的情况。
MEDIUM
是停靠点顺序不符合阅读顺序、没有可见焦点环,或停靠点隐藏在屏幕外的情况。复合控件中每个项目各占一个 Tab 停靠点,或 overlay 无法通过 Escape 关闭,也属于
MEDIUM
。
LOW
是缺少 skip link,或报告未提供编号停靠点。
格式。 每个根本原因只报告一个问题,并进行编号且引用对应的停靠点:
1. file:line - [rule-id] stop N, key, what is wrong
找不到源代码行时,引用记录器中的对应元素。随后附上
Rule | Count | Severity
汇总。只要仍有任何
HIGH
,结论即为
Block
;否则为
Approve
。将跨源 frame 内的内容标记为
Not verified
。