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

Vapor Mode でアクセシビリティは 壊れないか検証した話

Avatar for fuqda fuqda
October 24, 2026

Vapor Mode でアクセシビリティは 壊れないか検証した話

Avatar for fuqda

fuqda

October 24, 2026

More Decks by fuqda

Other Decks in Programming

Transcript

  1. Vue Fes Japan 2026 目次 1. 2. 3. 4. 5.

    この発表の前提とその補足 どう測ったか 自動テストによる検証 スクリーンリーダーによる手動検証 まとめ 03
  2. 1. この発表の前提とその補⾜ Vue 3.6 の Vapor Mode は、仮想 DOM を介さず

    DOM を直接組み立てる、 Vue 公式の新しいレンダリング方式です 速さが話題になりがちですが、DOM の更新のしかたも変わります 07
  3. 1. この発表の前提とその補⾜ スクリーンリーダーはアクセシビリティツリーを読んでいます アクセシビリティツリー ← スクリーンリーダーが読む DOM(書いたもの) region "フォーカス管理 :

    …" <section aria-labelledby="focus-heading"> <h2 id="focus-heading">フォーカス管理: …</h2> heading "フォーカス管理 : …" <button>設定を開く</button> button "設定を開く " <div role="dialog" ブラウザ が変換 dialog "設定" [modal] aria-modal="true" aria-labelledby="focus-dialog-heading"> ▪ ロール(要素の種類) ▪ 名前 [ ] = 状態やプロパティ region = 名前の付いた section そのもの heading = その中の⾒出しの 1 ⾏ 11
  4. 2. どう測ったか 同じ Vue ファイルを、フラグで 2 系統にビルドしました Vite の Vue

    プラグインの features.vapor を false / true に切り替え、Vue のコンパイラが出す JS を分けています apps/classic vapor: false source/ components/ pnpm run sync apps/vapor vapor: true 13
  5. 2. どう測ったか アクセシビリティの差が出そうな 11 場面を選びました 1 トースト通知を出す 2 モーダルダイアログを開く 3

    アコーディオンを開閉する 4 フォームの⼊⼒エラーを出す 5 ヒント⽂を出し⼊れする 6 リストを並べ替える 14
  6. 2. どう測ったか アクセシビリティの差が出そうな 11 場面を選びました 7 ⼊⼒欄と⽂字数カウンタ 8 Teleport を利⽤したモーダルダイアログ

    10 表⽰中のパネルを差し替える 11 簡易的な SSR での検証 9 アニメーションでの表⽰切り替え 15
  7. 2. どう測ったか 11 場面を 2 つのやり方で検証 ⾃動テストによる検証 Playwright で、アクセシビリティツリーを⽐べます 11

    場⾯ スクリーンリーダーによる⼿動検証 Mac 標準の VoiceOver で、読み上げを聞き⽐べます 16
  8. 3. ⾃動テストによる検証 スナップショットテストでアクセシビリティツリーを比較しました Playwright の ariaSnapshot() で、状態ごとに撮影 - 'region "フォーカス管理

    : モーダルダイアログの検証 "': - button "設定を開く " - dialog "設定": - heading "設定" [level=3] - button "閉じる" この yaml を classic と vapor で⽐べます 18
  9. 3. ⾃動テストによる検証 差は 0 件でした 57 通りすべてで、classic と vapor の

    ariaSnapshot の結果が完全に⼀致しました 差 # 57 通りの ariaSnapshot を比べる $ diff -r snapshots/classic snapshots/vapor $ echo $? 0 0 57 / 57 ⼀致 19
  10. 4. スクリーンリーダーによる⼿動検証 同じ操作をして、読み上げた文を並べて比べます 11 場⾯を、classic → vapor の順に確かめました 1. 2.

    3. classic と vapor で、同じキー操作を行います VO + → で 1 つずつ読み進め、 Tab でボタン間を移動します 読み上げた文を、クリップボードにコピーして残します VO + Shift + C で、直前に読み上げた文をコピーします 2 つの文字列を、操作ごとに並べて比べます 22
  11. 4. スクリーンリーダーによる⼿動検証 11 場面すべてをスクリーンリーダーで読み上げた結果 1. ⼀致 トースト通知 2. 差あり モーダルダイアログ

    3. ⼀致 アコーディオン 4. ⼀致 フォームの⼊⼒エラー 5. ⼀致 ヒント⽂の出し⼊れ 6. ⼀致 リストの並べ替え 7. ⼀致 ⽂字数カウンタ 8. ⼀致 Teleport を利⽤した モーダルダイアログ 9. ⼀致 アニメーションでの 表⽰切り替え 10. ⼀致 パネルの差し替え 11. ⼀致 簡易的な SSR ⼀致は、classic と vapor の読み上げが⼀字⼀句同じだったものです 23
  12. 4. スクリーンリーダーによる⼿動検証 モーダルダイアログの検証コード(抜粋) <section aria-labelledby="focus-heading"> <h2 id="focus-heading">フォーカス管理 : モーダルダイアログの検証 </h2>

    … <div v-if="isOpen" ref="dialogRef" role="dialog" aria-modal="true" aria-labelledby="focus-dialog-heading" tabindex="-1"> <!-- tabindex="-1": 開いたときにダイアログ自体へフォーカスを置くため --> … </div> </section> モーダルダイアログは名前の付いた section の中です。読み上げカーソルをモーダルダイアログの外へ出し、この section の名前を読むかを検証しました 24
  13. 4. スクリーンリーダーによる⼿動検証 アクセシビリティツリーには、ちゃんと残っていた! モーダルダイアログを開いた状態で、Safari の Web インスペクタで親の section を⾒ました CLASSIC

    VAPOR ロール region(デフォルト) ラベル フォーカス管理: モーダルダイアログの検証 ロール region(デフォルト) ラベル フォーカス管理: モーダルダイアログの検証 ✓ ✓ 28
  14. 5. まとめ この発表で紹介したやり方 検証結果は環境とバージョンで変わることがあるので、やり方を紹介します 1. 1 ソース 2 系統 vapor

    フラグの false / true で 2 系統に分けます 2. ariaSnapshot で比較 状態ごとに撮った yaml を比べます 3. 差が出たときの切り分け ① 毎回リロードから 3 回やり直して、再現するか見ます ② Web インスペクタで、ブラウザのアクセシビリティツリーを直接見ます ③ 両方に名前があれば、アクセシビリティツリーより先( Safari から VoiceOver まで)を疑います github.com/Shigeyuki-fukuda/vue-vapor-a11y-experiment 31