keyboard について
Keyboardは、キーボード操作だけで実行中のWebページを監査するスキルです。フォーカス位置を順に記録し、到達・識別・操作できないコントロールを、番号とキーに紐づけて報告します。
主な機能
- 01TabとShift+Tabでフォーカス位置を記録
- 02フォーカス順と可視インジケーターを確認
- 03キーボードで到達できないコントロールを検出
- 04キーボード操作とオーバーレイの動作を検証
- 05位置番号とキーを添えて問題を報告
活用シーン
- 01マウスを使わずにページを監査
- 02キーボード利用者が到達できないコントロールを特定
- 03メニューやダイアログのキーボード動作を確認
- 04コンテンツ変更や削除後のフォーカス喪失を記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ raphaelsalaja/ skills --skill keyboardインストール後、Claude Code で/keyboardを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamltabstops.js
詳細
キーボード
このスキルではマウスを使わず、キーだけで実行中のページを操作します。フォーカスが止まる箇所を順に記録し、キーボードで到達、確認、操作できない箇所を番号付きで報告します。
すべての停止箇所をキーで確認し、コードから判断しない
フォーカス順序、到達可能性、操作可能性は、実行中のページでキーを押して判断します。操作中にキーで確認しなかった停止箇所は、推測せず Not verified とします。どんなに些細な操作部品でも、到達できなければ指摘事項です。
フォーカスリングの見え方、ダイアログのフォーカストラップ、アクセシブルネームは defaults の対象で、そこでの不具合はその ID を引用します。実行結果を開くのは verify の対象です。非表示の状態を強制的に開くのは lab の対象です。
1. レコーダーを読み込む
ユーザーが指定した状態でページを開き、何もクリックしないでください。ブラウザーの評価呼び出しを使って tabstops.js を実行します。キーボードで到達できないポインター対象が返された後、キーを押すたびに各停止箇所が記録されます。マークアップから順序や到達可能性を判断するのは keyboard-press-the-keys です。
Playwright の keyboard.press やオペレーティングシステムなど、信頼された入力を使ってキーを送信してください。DOM に対して KeyboardEvent をディスパッチしてもフォーカスは移動しないため、停止箇所がない場合はキーが届いていません。
2. 前方へ進み、戻る
ページの先頭からフォーカスがページの外に出るまで 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 を引用します。
ナビゲーションがメインコンテンツより前にある場合、最初の停止箇所はメインコンテンツへのスキップリンクです。最初の検索結果までにヘッダーで 20 回停止する場合は keyboard-skip-link です。
3. すべての操作部品に到達する
停止箇所を、ページに表示される内容およびレコーダーの unreachable リストと照合します。クリック可能な div にキーボード操作でフォーカスが移らない場合は keyboard-reach-every-control です。
4. 各操作部品を操作する
ボタンは Enter と Space、リンクは Enter、チェックボックスとスイッチは Space で操作します。クリックには反応しても、キーには反応しない操作部品は keyboard-operate-every-control です。
メニュー、タブ、ラジオグループ、リストボックス、グリッドでは Tab の停止箇所は 1 つで、内部は矢印キーで移動します。各項目がそれぞれ Tab の停止箇所になっているメニューは keyboard-arrows-inside-composites です。
Escape で開いているメニュー、ポップオーバー、シート、ダイアログを閉じます。クリックでしか閉じられないオーバーレイは keyboard-escape-closes です。
5. 各オーバーレイを開閉する
キーボードで各ダイアログ、メニュー、ポップオーバーを開きます。フォーカスは内部に移動し、モーダル内にとどまり、閉じるとトリガーに戻ります。不具合は defaults-trap-and-return-focus を引用します。
6. 項目を削除してから、フォーカスを確認する
キーボードで行を削除し、トーストを閉じ、セクションを折りたたみ、フォームを送信します。フォーカスは隣接する項目、コンテナー、または結果に移ります。レコーダーが lost と記録し、フォーカスが body に残る停止箇所は keyboard-focus-survives-removal です。
7. 操作結果を報告する
highlight() の番号が表示されたスクリーンショットとともに、停止箇所をロールと名前の番号付きリストで返します。各指摘事項には、該当する停止箇所の番号と失敗したキーを記載します。停止箇所番号もキーもない指摘事項は keyboard-numbered-walk です。
ペア
各チェックはペアです。問題のある行と、その置き換えとなる行を並べています。
| ルール | 問題のある状態 | 置き換え後 |
|---|---|---|
keyboard-press-the-keys | 「マークアップにはボタンが使われているため、操作できます」 | 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 | 最初の検索結果までにヘッダーのストップが 20 個ある | ストップ 1 に Skip to Content リンクを置く |
keyboard-reach-every-control | <div onClick={openRow}> | <button onClick={openRow}> |
keyboard-operate-every-control | クリックでしか切り替わらないスイッチ | Space で切り替わる |
keyboard-arrows-inside-composites | 1 つのメニュー内に Tab ストップが 8 個ある | ストップは 1 つで、矢印キーで項目間を移動 |
keyboard-escape-closes | 外側をクリックしたときしか閉じないポップオーバー | Escape で閉じ、フォーカスがトリガーに戻る |
keyboard-focus-survives-removal | 行を削除した後、フォーカスが body にある | 次の行にフォーカスがある |
keyboard-numbered-walk | 「キーボード対応にばらつきがある」 | 「ストップ 12、Notifications で Space を押しても何も起きない」 |
報告
重大度。 HIGH は、キーボードで到達または操作できないコントロール、あるいは操作後にフォーカスが body に失われるケースです。MEDIUM は、読み上げ順と異なるストップ、見えるリングのないストップ、画面外に隠れたストップです。項目ごとに Tab ストップがある複合コントロールや、Escape で閉じないオーバーレイも該当します。LOW は、スキップリンクがないケース、またはストップ番号のない報告です。
形式。 根本原因ごとに 1 件ずつ、番号を付けてストップを明記します。
1. file:line - [rule-id] stop N, key, what is wrong
ソース行が見つからない場合は、レコーダーが記録した要素を明記します。続けて Rule | Count | Severity の概要を記載します。HIGH が 1 件でも残っている場合は Block、それ以外は Approve とします。クロスオリジンフレーム内のコンテンツには Not verified と記します。