Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Native と アクセシビリティ

grgr-dkrk
March 04, 2021
790

React Native と アクセシビリティ

1 タイトル
React Native とアクセシビリティというテーマについて発表いたします。よろしくお願いいたします。

2 自己紹介
自己紹介です。ぐるぐるできるこ、という名前です。株式会社 CureApp で医療用アプリケーションの開発をしております。以上です。
(発表内容は所属する企業、団体と一切関係ありません。)

3 アクセシビリティ
今回のテーマのアクセシビリティですが、この言葉自体は、誰もがどんな状況や環境でも不自由なくアプリを使えるという意味として捉えておいてください。
人が画面を通して目視可能であると同時に、マシンが認識可能なマシンリーダブルである、ということもアクセシビリティと言えます。
今回はこの「マシンリーダブル」寄りのお話となります。
(アクセシビリティの定義について議論する回ではありません)

4 マシンリーダブルとは
マシンリーダブルというのは、マシン、今回で言えば端末が読み取れるということです。
アプリ上で目視可能なコンテンツであっても、端末側では情報を読み取れなかったり、誤って認識される可能性があります。

5 マシンリーダブルでないと言う例
どういうことかって話ですが、「もどる」ボタンがモバイルの画面に表示される例を考えてみましょう。
React Native でコードを書くと Pressable コンポーネントを設置して、その中に「もどる」の画像を設置する感じになると思います。

6 マシンリーダブルでないと言う例2
ところが、これはマシンリーダブルではありません。
まず、これは React Native の罠なのですが Pressable はただの View のラッパーです。この場合ボタンではなく View として認識されます。
また、ボタンを押した時に何が起こるのかがわかりません。
そして、画面を見るまでこれが「戻る」ボタンだとはわかりません、言い換えると何の画像かわかりません。

7 マシンリーダブルでないとどうなる
マシンリーダブルでないどどうなるかですが、一番の問題としては、補助機能にコンテンツの情報を提供できなくなることです。
例えば、画面が見られないユーザーがいる場合に、スクリーンリーダーというのを使って画面の情報を読み上げようとしますが、正しい情報が提供されていないので、
コンテンツが読み上げられなくなる上に、インタラクションであれば操作が困難になります。

7.補足
スクリーンリーダーというのですが iOS の VoiceOver や Android の TalkBack が使われます。
機能の詳細には触れませんが、このような機能でアプリを使用するケースもあるので、マシンリーダブルであることが望ましいです。

8 マシンリーダブルにするために
マシンリーダブルにする方法は 2 つあります。理想は標準のコンポーネントに乗っかることですが難しいので、今回はもう一つの「追加の情報を与える」という方法を紹介します。

9 追加の情報を与えることについて
追加の情報を与えるというのは、コンポーネントに属性を持たせることです。
表は、主要な属性をまとめたものです。コンポーネントの名前を示すラベル、特性や状態を示すトレイト、ボタンを押した時などのアクションに対してどんな事が起こるかを説明するヒントという属性があります。

これ自体は iOS の概念なんですけども、React Native は OS 同士での一貫性を保つように頑張りますので、Android でも同じように考えることができます。

10 React Native と OS 側のアクセシビリティ API とのやりとり
そもそも iOS と Android は言語や実装が全然違ってて、特定の OS にしかない機能とかもあります。
React Native では JavaScript 側に専用の Props や API を渡し、そこからネイティブの処理を呼びだしています。
ネイティブ側ではそれらを直接マッピングするなり、ヘルパー経由でいい感じにマッピングしていくなどをやっています。

11 マシンリーダブルにするため React Native でやること
そのため React Native では、スライドにあるような Props や API を渡すことで、ある程度対応できるようになっています。(accessible, accessibilityRole, accessibilityLabel, accessibilityState, accessibilityHint など…)

12 4, 5 ページをマシンリーダブルにした例
実際に Props を渡して、先ほどの戻るボタンをマシンリーダブルにしてみました。
これでスクリーンリーダーでは「もどる、button、前のページに戻ります」と読み上げます。
まず accessibilityLabel で「もどる」というラベルをつけて、accessibilityHint で、押した時に前のページに戻ることを示すようにしました。
おまけにロールというものを設定しました。
ロールというのはトレイトです。iOS のトレイトは「特性と状態」の2つを兼ねていますが、React Native では「特性」の方を、ロールという Props で切り出しています。Android との違いを合わせるためだと思います。
それでなぜこれがオマケかと言いいますと、このロールの実装が微妙でして、Android で読み上げが英語に固定されるためです。

12(デモ)
省略
こうでもしなければマシンリーダブルにならん、というのはなかなか辛いものがあると思います。

13 チェックツールの宣伝
そこで唐突な宣伝ですが、チェック用の ESLint Plugin を作ってます。
これを使えば先ほどのような罠を覚えてなくても、ある程度チェックしてくれます。
スターくれ、というのを言いたかっただけです。
https://github.com/grgr-dkrk/eslint-plugin-rn-a11y

14 React Native はアクセシビリティ対応が良くない
さて、React Native はアクセシビリティのサポートが良くないことで有名です。
http://www.takingnotes.co/blog/2018/11/09/react-native-accessibility/

15 昔の React Native の表明
そもそも React Native はバージョン 0.5 の頃に、アクセシビリティのことを考えずにアプリを作っても 80% のアクセシビリティ対応ができることを目標にしていました。
https://github.com/facebook/react-native/releases/tag/v0.5.0-rc

16 Airbnb がやめた理由のひとつ
一方で、2018 年に React Native をやめた Airbnb は、アクセシビリティ対応をするために、fork して修正したバージョンをビルドするという辛い現実を話しています。
https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838

17 問題点
よく言われてる問題点をまとめてみました。
まず各 OS のアクセシビリティ API に対応しきれていないことが挙げられます。これはクロスプラットフォーム故の辛さでもあり、React Native ではネイティブ側のヘルパーなどの実装もあるため、対応にラグがある、とも言えます。
詳細は割愛しますが、基本的にネイティブの機能は規格やガイドラインなどでアクセシブルになってます。それで言えば React Native は Native になりきれていないことの弊害がここに出てしまっています。

あと、アクセシビリティ用の API や Props がこなれていない問題や、組み込みコンポーネントやライブラリのアクセシビリティ対応が良くないなどの問題もあります。

18 改良されている話
一部の問題は少しずつ改善されています。
まず Airbnb がやめた頃ぐらいに、React Native プロジェクトに参画していたインターンの方が改良を施しました。
アクセシビリティのイケてない実装を見直して、各 OS の差異を可能な限り吸収して、一貫性のある設定ができるようになりました。
代表的なもので言えば、今までまともに扱えなかった Hint 属性をサポートできたことがあります。
https://www.linkedin.com/pulse/react-native-a11y-ziqi-chen

最近では React Native でプロジェクトが動き始めていて、作業が進んでいるようです。
その作業は GitHub の Project で確認できます。
https://github.com/facebook/react-native/projects/15

19 課題
よって昔ほど酷くないとは言えますが、それでも不具合や未対応の機能が多く、80% の対応は厳しいところです。
組み込みコンポーネントでさえ、十分な機能を提供できてません。
先ほどの「戻る」ボタンの例みたいな、「Pressable なのにボタンじゃないのかよ」みたいな問題などです。
あと本体だけ直せばいい話でもなくて、UI ライブラリのアクセシビリティ改善も見直さなければなりません。
(特に一時期は某 Navigation ライブラリがよく槍玉に挙げられたりしました。)

これらのことから、アクセシビリティ観点だと現状 React Native の採用はつらい、というのが正直なところです。
今後に期待です。

20 我々ができること
今からできることはあると思います。
(支援技術を使った操作方法については割愛)

まず、UI の説明が見た目に依存していないかを意識することができるようになると思います。
言い換えますと、画面からの認知だけで成り立つ UI ではなく、セマンティクス、コードとしての UI があるかどうかです。

その中で、ラベル、トレイト、ヒントの概念を思い出してみましょう。
これらは完全なネイティブの振る舞いを再現しませんが、ある程度はカバーできるようになっています。
悲しいですが、まだまだイケてない機能もあります。ロールとかです。

あとは改善を祈るか Contribute していこうなという世界観です。

補足1. React Native の専用ページ
アクセシビリティ関連のドキュメントがあります。
https://reactnative.dev/docs/accessibility
https://reactnative.dev/docs/accessibilityinfo

補足2. 参考
(省略)
Starting A11Y in iOS (https://speakerdeck.com/ra1028/starting-a11y-in-ios)
React Native at Airbnb: The Technology (https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838)
React Native Accessibility Is Pretty Bad (http://www.takingnotes.co/blog/2018/11/09/react-native-accessibility/)

22 終わりのページ
React Native がユーザーと開発者にとってのアクセシビリティを実現できる時代が来ることを望みます。
以上です。ありがとうございました。

grgr-dkrk

March 04, 2021
Tweet

Transcript

  1. スクリーンリーダー • iOS の VoiceOver • ホームボタン、またはロックボタンをトリプルタップ • 左右スワイプでコンテンツ移動、読み上げる •

    Android の TalkBack • 音量+、音量- ボタンを同時に 3 秒以上押す • 左右スワイプでコンテンツ移動、読み上げる
  2. React Native とのやりとり 専用の Props や AccessibilityInfo API など ネイティブ側の

    プロパティにマッピング AccessibilityDelegate View からオーバーライド いい感じヘルパー
  3. React Native とのやりとり • accessible : フォーカス可能にする • accessibilityRole :

    「特性」のトレイト • accessibilityLabel : ラベル • accessibilityState : 「状態」のトレイト • accessibilityHint : ヒント • AccessibilityInfo (API) : アクセシビリティ関連の情報をやり取りする React Native が提供する Props や API を使用して対応
  4. 2018: Airbnb のお言葉 https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838 )PXFWFS UIFSFXFSFNBOZIPMFTJOUIF3FBDU/BUJWFBDDFTTJCJMJUZ"1*T*OPSEFS UPNFFUFWFOBNJOJNVNBDDFQUBCMFBDDFTTJCJMJUZCBS XFIBEUPNBJOUBJOPVS PXOGPSLPG3FBDU/BUJWFXIFSFXFDPVMENFSHF fi

    YFT 【意訳】 (中略)しかし、React Native のアクセシビリティ API には多くの欠陥がありました。 最低限のアクセシビリティ対応のために修正を fork にマージして メンテナンスしなければなりませんでした。
  5. React Native 問題点 • OS のアクセシビリティ API に対応しきれてない • クロスプラットフォーム故のつらみ

    • Native になりきれていないことの弊害 • アクセシビリティ API や Props がこなれていない • OS で役割が同じなのに全く別の属性、値が必要 • 組み込みコンポーネント、ライブラリのアクセシビリティ対応が良くない • そもそもテキストを認識させない • 自分を Button と思い込んでいる View とか
  6. 改善の動き • 2018: インターンの活動で RN のアクセシビリティ辺りが見直された • 各 OS の差異を可能な限り吸収し、一貫性を担保した(Hint,

    Role など) • https://www.linkedin.com/pulse/react-native-a11y-ziqi-chen • 最近: RN アクセシビリティチームの GitHub project • https://github.com/facebook/react-native/projects/15
  7. 今でもできること 1. UI の説明が、見た目に依存してないかを意識する シグニファイア(認知に依存する UI)ではなく、コードで説明可能か? 2. Label, Traits, Hint

    を思い出してみる ネイティブの振る舞いは再現してないが、ある程度はいけるはず。 ただし、日本語圏では微妙なものもある(Role など) 3. 改善を祈る。または Contribute
  8. 参考 Starting A11Y in iOS (Label, Traits, Hint) https://speakerdeck.com/ra1028/starting-a11y-in-ios React

    Native at Airbnb: The Technology (つらい話1) https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology- dafd0b43838 React Native Accessibility Is Pretty Bad (つらい話2) http://www.takingnotes.co/blog/2018/11/09/react-native-accessibility/