004_multi-open
複数項目を同時に開ける挙動はバニラJS実装の自然な振る舞いですが、項目数が増えると「全部見たい/全部畳みたい」というニーズが出ます。
本スニペットは snippet 001 をベースに、「すべて開く/すべて閉じる」一括操作ボタンを追加した実装です。
個別開閉と一括操作は aria-expanded を真実の源として共有し、状態が常に一致します。
一括操作後はスクリーンリーダーへ状態変化を通知し、全開/全閉時は対応するボタンを無効化して状態を視覚化します。
各項目が独立した情報を持ち、ユーザーが複数項目を同時に参照したい場面に向いています。 たとえばFAQで複数の質問を見比べたい・設定パネルで複数セクションを並行して編集したい等のユースケースです。
逆に「読ませたい順序がある」「画面領域を1項目分しか確保できない」場合は排他制御型(snippet 005 single-open)が向いています。
項目が10個・20個と増えると「順に開いていく」「個別に閉じていく」操作の手数が地味に重くなります。 一括操作ボタンを置くと、ユーザーは「全体を一度に俯瞰したい」「読み終わったので畳みたい」というニーズに即応できます。
本スニペットでは、現在の状態に応じてボタンを disabled 化します。
全項目が閉じている時は「すべて閉じる」を、全項目が開いている時は「すべて開く」を無効化することで、
「押しても何も起きないボタン」を視覚的・支援技術的に明示しています。
個別ヘッダーのクリック・一括ボタンのクリックのいずれの経路でも、
最終的に同じ setItemState(header, open) 関数を経由して
aria-expanded と hidden を同時更新する設計にしています。
操作後は updateBulkButtonsState() で全項目の状態を見直し、
「すべて開く/すべて閉じる」ボタンの disabled 状態をDOMに反映します。
これにより個別経由・一括経由のどちらで操作しても、画面上の状態が常に一致します。
個別ヘッダーの開閉は aria-expanded の切替で支援技術に状態が伝わるため、追加の通知は不要です。
一方、一括操作はフォーカス位置(一括ボタン)と状態変化の起こる場所(個別項目)が離れているため、
role="status" + aria-live="polite" を持つ視覚的に隠したライブリージョンに
「すべて開きました/すべて閉じました」というテキストを差し込むことで、
画面外で起きた変化をスクリーンリーダーに通知しています。