サンプルコードで身につける: Angular Aria — アクセシビリティを部品で担保する
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1自前実装だと何が大変か — ARIA属性の手書き
アクセシブルなタブUIを自前で作ると、role や aria-* 属性を全要素に正しく付けて回る必要があります。しかも選択状態が変わるたびに aria-selected や tabindex を全部更新しなければならず、抜け漏れがそのまま支援技術の誤動作になります。Angular Aria が肩代わりしてくれるのは、まさにこの部分です。
// タブUIを「見た目だけ」で作った場合と、正しく作った場合の差
//
// 見た目だけのタブ(スクリーンリーダーにはただの div の羅列):
// <div class="tab">概要</div>
// <div class="tab">レビュー</div>
//
// 正しいタブに必要な属性(これを手書きで管理することになる):
// <div role="tablist">
// <button role="tab" aria-selected="true" aria-controls="panel-1" tabindex="0">概要</button>
// <button role="tab" aria-selected="false" aria-controls="panel-2" tabindex="-1">レビュー</button>
// </div>
// <div role="tabpanel" id="panel-1">...</div>
//
// タブを切り替えるたびに aria-selected と tabindex を
// 全タブぶん更新し続ける必要があり、抜け漏れが起きやすい
2自前実装だと何が大変か — キーボード操作
ARIAの慣習では、タブは矢印キーで移動し、Home / End で端へ飛べることが期待されます。これを自前で書くと、キーごとの分岐とフォーカス管理のコードが部品ごとに必要になり、テストも含めると相当な量になります。この振る舞いを部品側が最初から持っている、というのが Angular Aria の価値です。
// タブに期待されるキーボード操作(ARIAの慣習)を自前で書いた場合の骨組み
function onKeydown(event: KeyboardEvent, current: number, tabCount: number): number {
switch (event.key) {
case 'ArrowRight':
return (current + 1) % tabCount; // 次のタブへ(末尾なら先頭へ)
case 'ArrowLeft':
return (current - 1 + tabCount) % tabCount; // 前のタブへ
case 'Home':
return 0; // 先頭のタブへ
case 'End':
return tabCount - 1; // 末尾のタブへ
default:
return current;
}
}
// さらに移動先の要素へ focus() を当て、tabindex を付け替える処理も必要。
// メニューやアコーディオンでも同種のコードを毎回書くことになる
3Angular Aria の役割分担
Angular Aria は「振る舞いとアクセシビリティ」だけを提供し、見た目は一切持ちません。開発者はCSSと業務ロジックに集中し、role / aria-* の付与、矢印キーでの移動、フォーカス管理は部品側が担保します。この分担を頭に入れておくと、どこまで自分で書くべきかの判断に迷いません。
// Angular Aria の役割分担
//
// ┌── 開発者がやること ─────────────────────
// │ ・CSSで見た目を作る(色・余白・アニメーション)
// │ ・業務ロジックを書く(どのタブを出すか、何を保存するか)
// └─────────────────────────────────────
//
// ┌── Angular Aria がやること ──────────────
// │ ・role / aria-* 属性の付与と更新
// │ ・矢印キー・Home / End などのキーボード操作
// │ ・フォーカスの管理(どこにフォーカスを置くか)
// └─────────────────────────────────────
//
// スタイルを一切持たないので、見た目は自分のデザインに
// 自由に合わせられる(「ヘッドレス」な設計)
4タブUIをディレクティブで組み立てるイメージ
Angular Aria を使うと、タブ・メニュー・アコーディオンなどの操作部品を、要素にディレクティブを付ける形で組み立てられます。ARIA属性とキーボード操作はディレクティブが自動で面倒を見るため、テンプレートには構造とCSSクラスだけを書けばよくなります。具体的なディレクティブ名や使い方は、v22時点の公式ドキュメントで確認してください。
// Angular Aria でタブUIを組み立てるときの考え方(擬似コード)
// ※実際のディレクティブ名・APIは公式ドキュメントを参照
//
// テンプレートの構造イメージ:
// <div タブリストのディレクティブ class="my-tabs">
// <button タブのディレクティブ>概要</button>
// <button タブのディレクティブ>レビュー</button>
// </div>
// <div パネルのディレクティブ>概要の中身</div>
// <div パネルのディレクティブ>レビューの中身</div>
//
// ・role / aria-selected / tabindex はディレクティブが自動で付与・更新
// ・矢印キーでのタブ移動、フォーカス制御も部品側が処理
// ・開発者が書くのは .my-tabs などのCSSと、タブの中身だけ
5Angular Material との役割の違い
同じ公式ファミリーでも、Angular Material は「見た目まで完成した部品」、Angular Aria は「振る舞いとアクセシビリティだけの部品」で役割が違います。デザインを独自に作りたいがキーボード操作やスクリーンリーダー対応は正しくしたい、という場面が Angular Aria の出番です。選定のときにこの軸で考えると迷いません。
// Angular Material と Angular Aria の使い分け
//
// Angular Material:
// ・見た目(マテリアルデザイン)まで完成した部品集
// ・すぐ使えるが、デザインを大きく変えるのは苦手
//
// Angular Aria:
// ・振る舞いとアクセシビリティ「だけ」を提供(スタイルなし)
// ・見た目は自分のCSSで自由に作れる
//
// 選び方の目安:
// 社内ツールなど、標準的な見た目で速く作りたい → Material
// 独自デザイン + 正しいキーボード操作/支援技術対応 → Angular Aria
//
// どちらも「アクセシビリティを自前で全部書かない」ための選択肢