eslint-plugin-jsx-a11y を導入する
🔦

eslint-plugin-jsx-a11y を導入する

#A11Y#React#TypeScript

By jiyuujin at

eslint-plugin-jsx-a11y を導入する

当方 React (CRA/Vite) のプロジェクトにおけるアクセシビリティを考慮するため をインストールすることとした。

# npm
npm i -D eslint-plugin-jsx-a11y

# yarn
yarn add -D eslint-plugin-jsx-a11y

実際に導入する

下記のように .eslintrc.jsextendsplugins に設定する。

module.exports = {
  extends: ['plugin:jsx-a11y/recommended'],
  plugins: ['jsx-a11y'],
}

ルールセット

ルールセットは 2 種類ある。

  • jsx-a11y/recommended
  • jsx-a11y/strict

基本的にどちらのルールセットを使っても構わない。

対応ルール全てエラーと認識してくれる一方、一部ルールではエラーと見做さないケースも設定できたりなど、弾力的に運用できる。

まず、マウスやキーイベントのリスナーなどに role を付ける。

該当のルールは下記の通りです。

次に、非対話型の HTML 要素や WAI-ARIA ロールはマウスやキーイベントのハンドラーをサポートしないので role を付ける。

::: message is-primary

非対話型の HTML 要素

  • <main>
  • <area>
  • <h1>
  • <h2>
  • <h3>
  • <h4>
  • <h5>
  • <h6>
  • <p>
  • <img>
  • <li>
  • <ul>
  • <ol>

非対話型の WAI-ARIA ロール

  • <article>
  • <banner>
  • <complementary>
  • <img>
  • <listitem>
  • <main>
  • <region>
  • <tooltip>

:::

該当のルールは下記の通りです。

最後に th 要素のみ scope を許容する。

該当のルールは です。

あらゆる warning を解決する

eslint-plugin-jsx-a11y を読み込んで eslint --fix してみる。

# eslint
npx eslint . --ext ts,tsx --fix

修正すべき warning に遭遇しなければ、導入完了とみて問題無いだろう。しかし、いくつかの warning に遭遇することがある。

具体的には div などに代表される静的な HTML 要素で onClick イベントを使ってしまっているケースなどが挙げられる。

jsx-a11y/click-events-have-key-events

onClick イベントを使う場合、マウスを使用できないユーザのために onKeyUp / onKeyDown / onKeyPress を考慮する必要がある。

もちろん 1 つも無ければ、アクセシビリティ的にアウトだ。

const Component = () => (
  <div onClick={() => {}}>
    {/* 何らかのコンテンツ */}
  </div>

)

なお、広くボタン用途に使われる button 要素で onClick イベントを使用した方が良い。

この button 要素では既に onKeyUp / onKeyDown / onKeyPress が考慮されている。

const Component = () => (
  <button onClick={() => {}}>
    {/* 何らかのコンテンツ */}
  </button>
)

jsx-a11y/no-static-element-interactions

div など静的な HTML 要素でマウスやキーイベントを設定する場合に、要素の role 属性を設定する必要がある。

const Component = () => (
  <div onClick={() => {}} role="button">
    {/* 何らかのコンテンツ */}
  </div>
)

onClick イベントと合わせて role 属性を設定しても特に問題は無い。

ただし、広くボタン用途で使われる button 要素に変更する選択肢を取った方が良い。

const Component = () => (
  <button onClick={() => {}}>
    {/* 何らかのコンテンツ */}
  </button>
)

最後に

とあるプロジェクトで ESLint を設定した当初 70 近い warning を観測した。

✘ 68 problems (68 errors, 0 warnings)

Errors:
  29  jsx-a11y/click-events-have-key-events
  28  jsx-a11y/no-static-element-interactions
   5  jsx-a11y/aria-role
   2  jsx-a11y/media-has-caption
   2  jsx-a11y/anchor-is-valid
   1  jsx-a11y/no-autofocus
   1  jsx-a11y/no-noninteractive-element-interactions

しかし、そのどれもが同じようなエラーであるため、そこまで怖がる必要は無い。

アクセシビリティの ESLint に伴う --fix をビルド時に強制したことで、最低限の品質を担保させるようにした。

その他

でサポートされているルール一覧です。

視覚によるチェックでは確認しきれない部分を補うため、コードベースでコンポーネントごとに自動チェックする。

Rule Recommended Strict
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error error
error, with options error
error, with options error
error, with options error
error, with options error
error error
error error
error, with options error
error error
error error
error, with options error
error error