# 観点表: キーボードのみによる操作

キーボードでの確認は、**スクリーンリーダーでの確認とは別に行う必要がある**。本来はキーボード
のみでは操作できないところが、スクリーンリーダー自体を操作するキーバインドでは操作できて
しまうことがあるため。

キーボードフォーカスの移動は `Tab` と `Shift` + `Tab` で行う。しばしば `Tab` のみが考慮され、
`Shift` + `Tab` では意図しない結果になることがあるため、フォーカスに関係する確認は
**両方向で**行う。

UI コンポーネントの操作には、矢印キー、`Enter`、`Space`、`Esc` などを使用する。独自のキー操作が
定義されている場合、特に OS やブラウザの慣習を踏襲していない場合には、その説明が存在する
ことが望ましい。

---

### KBD-01: 追加コンテンツ（フォーカス）を消去できる

- WCAG: SC 1.4.13 (AA)
- 確認手段: `both`
- 判定: キーボードフォーカスによってツールチップ等の追加コンテンツが表示される場合、
  フォーカスを動かさずにそれを非表示にできること（`Esc` キーなど）。ただし、入力エラーを
  伝えるものや、他のコンテンツを隠したり置換したりしない場合は対象外。
- 重篤度の目安: 他のコンテンツが隠され続けるなら Major。それ以外は Normal。

### KBD-02: 追加コンテンツ（フォーカス）へフォーカスを移動できる

- WCAG: SC 1.4.13 (AA)
- 確認手段: `both`
- 判定: キーボードフォーカスによって追加コンテンツが表示され、その内部に操作を受け付ける
  ものがある場合、フォーカスをその内部へ移動でき、その間も追加コンテンツが表示され
  続けること。ただし、内部でできる操作が他の場所でもキーボードで行えることがわかりやすく
  なっていれば問題ない。
- `code` からの判定: ポップオーバーが `blur` で即座に閉じる実装になっていないか、
  内部の要素がフォーカス可能かを確認する。
- 重篤度の目安: 内部の操作を実行できないなら Major。

### KBD-03: 追加コンテンツ（フォーカス）が持続する

- WCAG: SC 1.4.13 (AA)
- 確認手段: `both`
- 判定: 追加コンテンツは、フォーカスが解除されるか、利用者の意図によって非表示にされるか、
  内容が無効になるような変化が起きるまで表示され続けること。時間経過で自動的に消えては
  ならない。
- 重篤度の目安: 内容を読み切れないなら Normal。重要な情報なら Major。

### KBD-04: すべての機能がキーボードで操作できる

- WCAG: SC 2.1.1 (A)
- 確認手段: `both`
- 判定: すべての機能がキーボードで操作できること。ただし、マウスポインタの軌跡の使用に
  依存する機能（お絵描き機能など）は除く。
  - この確認のために、**すべての操作をキーボードで行ってみるテスト**を、マウスポインタを
    中心とした操作とは別に行う。マウスポインタによる操作が通常の（アクセシビリティを主眼に
    置かない）テストで行われているのであれば、アクセシビリティチェックはキーボードでの操作を
    中心としたものにしてよい。
  - ドラッグ＆ドロップやマウスオーバーなど、マウスポインタ特有の挙動を必要とする機能には、
    キーボードのみで操作できる代替手段を提供しなければならない。
- `code` からの判定: 以下を探す。
  - `<div>` `<span>` など非対話要素への `onClick` / `@click`（`role` と `tabIndex` と
    キーボードイベントの3点が揃っていなければ操作できない）
  - `onMouseOver` / `onMouseEnter` のみで発火し、`onFocus` のハンドラがないもの
  - `tabIndex={-1}` によってフォーカスを受け取れなくされている操作可能要素
  - `href` を持たない `<a>` 要素（フォーカスを受け取れない）
  - `disabled` ではなく `pointer-events: none` で無効化されている要素
- 重篤度の目安: キーボード利用者がその機能を実行できないため、原則 Major。
  キーボード操作で主となるナビゲーションが機能しない、次のステップのページに進めないなど、
  そのページだけに留まらない影響があるなら Critical。

### KBD-05: キーボードトラップと、その解除

- WCAG: SC 2.1.2 (A)
- 確認手段: `both`
- 判定:
  - キーボードフォーカスが、キーボード操作だけでは抜け出せない場所に閉じ込められないこと
    （これが SC 2.1.2 の要件）
  - ドロップダウンメニューやモーダルダイアログが開くときは、一時的にその内部のみを
    フォーカスが移動するようにする（意図的なキーボードトラップを設置する）ことが望ましい。
    さらに、一般的なキーボード操作によってその制限を解除できるか、方法が利用者に
    通知されていること
- 補足: WCAG には、ドロップダウンメニューやモーダルダイアログにキーボードトラップを
  用意するべきとは書かれていないが、用意したほうがよい。
- 一般的な解除の操作方法として想定されるもの（いずれも必須ではない）:
  - `Esc` キーでメニューやダイアログが閉じられる
  - `Tab` / `Shift` + `Tab` または矢印キーによってメニュー項目を辿ることができる
  - ドロップダウンメニューを開くボタンにフォーカスを移動し、`Enter` または `Space` で
    メニューを閉じることができる
  - ダイアログを閉じるためのボタンが用意され（ラベルは「キャンセル」でも、挙動を利用者が
    想定できるものであればよい。バツ印のアイコンのみのボタンであることも多い）、そこに
    フォーカスを移動して `Enter` または `Space` で閉じることができる
- `code` からの判定: モーダル実装にフォーカストラップと `Esc` ハンドラ、および閉じた後に
  開いた元の要素へフォーカスを戻す処理があるかを確認する。`<dialog>` 要素の
  `showModal()` を使っている場合は、これらの多くがブラウザによって提供される。
- 重篤度の目安: 抜け出せないなら Critical（ページ全体が操作不能になる）。
  トラップがなくダイアログ外に出てしまうだけなら Normal。

### KBD-06: 文字キーのショートカット

- WCAG: SC 2.1.4 (A)
- 確認手段: `both`
- 判定: ブラウザの標準的なものに加えて、文字・数字・記号のみで構成されるキーバインド
  （ショートカットキー）が実装されている場合、以下のいずれかを満たすこと。
  - 解除できる
  - 修飾キーを含むように再割り当てできる
  - 特定の UI コンポーネントにフォーカスしているときのみ有効である
- `code` からの判定: `document` や `window` に対する `keydown` / `keypress` リスナーで、
  修飾キーを伴わない単独のキーを処理しているものを探す。
- よくある問題: 音声入力の利用者が発話しただけで、意図しない機能が実行される。
- 重篤度の目安: 誤発動の結果が重大なら Major。それ以外は Normal。

### KBD-07: フォーカス順序

- WCAG: SC 2.4.3 (A)
- 確認手段: `both`
- 判定: `Tab` / `Shift` + `Tab` でフォーカスを移動していったとき、利用者にとって自然だと
  感じられる順序で移動すること。
  - ページの冒頭から末尾まで `Tab` で移動し、末尾から冒頭まで `Shift` + `Tab` で移動した
    ときに、その順序が自然であること。また `Tab` と `Shift` + `Tab` で同じものに
    フォーカスが移動できること
  - 視覚的に見えないものにフォーカスが移動したり、フォーカスインジケーターが見えなく
    なったりしてはならない
- `code` からの判定: `tabindex` の正数指定（DOM 順序から外れるため原則使わない）、
  CSS の `order` / `flex-direction: row-reverse` / `grid` の配置による視覚順序と DOM 順序の
  乖離、`visibility: hidden` や `display: none` にせずに画面外へ飛ばしただけの非表示要素を探す。
- 重篤度の目安: 意図しない箇所に飛んで操作を続けられないなら Major。順序が不自然なだけなら
  Normal。

### KBD-08: フォーカスの可視性

- WCAG: SC 2.4.7 (AA)
- 確認手段: `both`
- 判定: `Tab` / `Shift` + `Tab` でフォーカスを移動したとき、またはドロップダウンメニューや
  タブバーや入力欄を操作しているとき、常にフォーカスされている要素がわかりやすく変化した
  表示になること。
  - 代表的なものは「フォーカスリング」の表示である。ただし、デフォルトの `outline` による
    表示はブラウザによって異なるため、`outline` のスタイルを調整するか、主要なブラウザでの
    表示を確認しておくべきである
  - ハイコントラストモードでは `box-shadow: none` のスタイルが強制される。このとき
    `outline: none` としているとフォーカスインジケーターが表示されないため、`outline` は
    非表示ではなく**透明**にしておくことが望ましい
- `code` からの判定: `outline: none` / `outline: 0` / Tailwind の `outline-none` `focus:outline-none`
  を探し、代替のフォーカススタイルが指定されているかを確認する。代替が `box-shadow` のみの
  場合は、ハイコントラストモードで消えることを指摘する。
- 重篤度の目安: 現在位置がわからず操作できなくなるため、原則 Major。

### KBD-09: フォーカスの隠蔽

- WCAG: SC 2.4.11 (AA)
- 確認手段: `page`（`code` では原因となる実装の推定まで）
- 判定: フォーカスを受け取った要素が、他のコンテンツによって完全に隠されないこと。
  - コンテンツに被さる表示をするもの（固定ヘッダー、固定フッター、Cookie バナー、
    チャットウィジェット）がある場合、フォーカスしているものが見えるよう、スクロールによって
    完全には隠されないようにしてあるべきである
  - モーダルダイアログでは、ダイアログの外にフォーカスが移動しないようにしておくべきである
- `code` からの判定: `position: sticky` / `fixed` の要素の存在を挙げ、`scroll-margin` /
  `scroll-padding` による回避が行われているかを確認する。実際に隠れるかは実ページで判定する。
- 重篤度の目安: フォーカス位置が見えなくなるため Major。

### KBD-10: フォーカス時の変化

- WCAG: SC 3.2.1 (A)
- 確認手段: `both`
- 判定: 要素がフォーカスを受け取っただけで、他のページへの移動、ページ内容の大きな変化、
  新しいブラウザウィンドウが開くといった、コンテキストの変化が引き起こされないこと。
- `code` からの判定: `onFocus` ハンドラ内での画面遷移、モーダルの表示、フォームの送信を探す。
- 重篤度の目安: `Tab` で移動しただけで操作が中断されるため Major。

### KBD-11: 入力時の変化

- WCAG: SC 3.2.2 (A)
- 確認手段: `both`
- 判定: 入力欄への入力や選択の変更だけで、他のページへの移動、ページ内容の大きな変化、
  新しいブラウザウィンドウが開くといったコンテキストの変化が引き起こされないこと。
  変化させる場合は、事前にその旨を利用者に伝えるか、明示的な実行ボタンを設ける。
- `code` からの判定: `<select>` の `onChange` での画面遷移やフォーム送信、
  入力途中での自動送信、`onChange` での大幅な表示切り替えを探す。
- よくある問題: セレクトボックスを選ぶと即座にページ遷移する（キーボードでは選択肢を
  矢印キーで辿る途中で遷移してしまう）。
- 重篤度の目安: 意図しない遷移で操作を完了できないなら Major。
