アクセシビリティ
thl-ui は WCAG 2.1 AA を目標としています。3 つのプレイグラウンドの全ページ(75 ルート × React / Vue / Angular、ライトモードとダークモード)を axe-core で監査しており、serious または critical の違反は 1 件もありません。
sh
node scripts/a11y.mjs http://localhost:5181 # React、serious/critical で失敗
node scripts/a11y.mjs http://localhost:5182 --dark # Vue、ダークモード
node scripts/a11y.mjs http://localhost:5183 --min moderate --json report.jsonコンポーネントが行うこと
| 領域 | 動作 |
|---|---|
| 色 | すべてのテキストと背景の組み合わせは 4.5:1 以上です(アクセシブルな色の組み合わせ を参照)。明るい塗りには暗い文字を使います |
| フォーム | Field は、中に置いたコントロールに <label for>、aria-describedby(ヘルプ / エラー)、aria-invalid を関連付けます。カスタムウィジェットにも aria-labelledby で対応します。エラーは role="alert" を使い、翻訳されます |
| Checkbox / Switch | ネイティブの input なので、キーボードやフォームでそのまま動作します。ラベルテキストがアクセシブルな名前になり、アイコンのみの用途には ariaLabel を使えます |
| Select | コンボボックスパターン: role=combobox + listbox、aria-activedescendant、矢印キー / Enter / Esc、先行入力検索 |
| 日付 / 時刻ピッカー | トリガーは aria-haspopup="dialog" と aria-expanded を持つ combobox です。カレンダーグリッドには完全な日付の aria-label が付きます |
| Slider | value / min / max / valuetext を持つ role=slider。矢印キー、Home / End、PageUp / PageDown に対応し、範囲のつまみは "Minimum" / "Maximum" と名付けられます |
| Tabs | roving tabindex、矢印キーは無効なタブをスキップ、Home / End、aria-controls / aria-labelledby |
| Modal / Drawer | aria-modal、フォーカストラップ、フォーカスの復元、Esc、スクロールロック。閉じた drawer は inert になります |
| Dropdown / Popover | aria-haspopup / aria-expanded / aria-controls はラッパーではなくあなたのトリガー要素に付きます。Esc でフォーカスが戻ります |
| Tooltip | ホバーとフォーカスで表示され、aria-describedby で関連付けられます |
| Progress | 値とローカライズされた名前を持つ role=progressbar |
| レイアウト | スキップリンク、header / nav / main / footer ランドマーク、サイドメニューの aria-current="page"、h1 のページタイトル |
| モーションと RTL | 論理 CSS プロパティを使うため、dir="rtl" でレイアウトが反転します。:focus-visible のリングはテーマカラーを使います |
開発者の責任
- アイコンのみのボタンには
aria-labelを付けてください:<ThlButton circle icon="heart" aria-label="いいね" />。 - コントロールは
label付きのFieldの中に置くか、aria-labelを付けてください。 - 自分で作るスクロール可能な領域には
tabindex="0"とラベルが必要です。 - カスタムカラー: テキストは 4.5:1 以上を保ってください。
--thl-color-xと--thl-on-x/--thl-color-x-textを必ずセットで上書きします。