【ITニュース解説】BulkActionsBar - Part 2 - Engineering a Robust and Accessible Bulk Actions Bar in React
2025年09月12日に「Dev.to」が公開したITニュース「BulkActionsBar - Part 2 - Engineering a Robust and Accessible Bulk Actions Bar in React」について初心者にもわかりやすく解説しています。
ITニュース概要
Reactで一括操作バーを開発した技術記事。画面サイズに合わせたボタン数自動調整、異なるサブメニュー挙動、サイドバーとの配置など、柔軟性とアクセシビリティを確保するUI設計の工夫を解説する。
ITニュース解説
ウェブサイトやアプリケーションでよく目にする、複数の項目を選んで一括で操作する「一括操作バー」は、一見シンプルに見えるかもしれないが、実はその背後には多くの技術的な課題と工夫が隠されている。この記事では、この操作バーを、ユーザーが快適に、そして誰でも使えるように(アクセシブルに)開発するための挑戦と、それをどう解決したのかを技術的な視点から詳しく解説する。
まず最初の課題は、画面の幅に合わせて、操作バーの中にいくつボタンを表示できるかを正確に計算することだった。ウェブサイトのレイアウトは、見る人の画面サイズやブラウザのウィンドウ幅によって常に変化する。CSSという見た目を整えるための基本的な技術だけでは、この変化に柔軟に対応し、最適なボタン数を動的に調整することは難しかった。
そこで開発者は、「useVisibleChildrenCount」という独自のカスタムフックを作成した。これは、特定のコンテナ(操作バー全体を囲む部分)の幅がどれくらいかを監視し、その幅の中にいくつ子要素(ここではボタン)が収まるかをリアルタイムで計算する役割を持つ。具体的には、「ResizeObserver」という機能を使って、コンテナのサイズが変わったことを検知すると、その都度、各ボタンの幅とボタン間の隙間を考慮しながら、合計の幅がコンテナの幅を超えない範囲で、何個のボタンが表示できるかを計算し直す。これにより、画面のサイズが変わっても、常に適切な数のボタンが表示され、残りのボタンはドロップダウンメニューなどに格納される、といった柔軟な表示が可能になったのだ。
次に大きな課題となったのは、ドロップダウンメニューの挙動だった。特に、メニューの中にさらにサブメニューがあるような「入れ子構造」を持つメニューを、デスクトップとモバイルの両方で使いやすく、かつアクセシビリティも確保しつつ実現するのが難しかった。開発には、アクセシビリティを高めるための高機能なライブラリ「react-aria-components」が使われている。このライブラリは、キーボード操作やスクリーンリーダーへの対応など、アクセシビリティに関する多くの機能を提供してくれるが、その分、メニューのDOM(ウェブページの構造)に関する厳密なルールがある。
最初の試みでは、サブメニューを親メニューのアイテムの中に「ポータル」という仕組みを使って表示しようとした。ポータルは、コンポーネントを本来の場所とは異なるDOMの場所に表示させる技術だ。この方法であれば、見た目上はサブメニューが親メニューの上に乗っかるように表示できると考えた。しかし、「react-aria-components」が想定するDOM構造と、ポータルによって実現された構造が一致せず、キーボードでのフォーカス移動や、どのメニューが現在開いているかといった管理がうまく機能しなかった。アクセシビリティ機能が損なわれてしまうため、この方法は断念された。
最終的に採用された解決策は、ドロップダウンメニューの「ルートコンテンツの置き換えとスタック状態管理」というものだった。これは、特にモバイル環境で効果を発揮する。例えば、メインメニューからサブメニューを開くとき、モバイルでは、サブメニューの内容が現在のメインメニューの内容と完全に切り替わるように表示される。まるで新しい画面に遷移したかのように見えるため、ユーザーは今、メニューのどの階層にいるのかを直感的に理解できる。この仕組みは、現在の表示をスタック(積み重ね)として管理し、一番上の要素だけを表示するという考え方に基づいている。これにより、「react-aria-components」が提供する強力なアクセシビリティ機能を損なうことなく、デスクトップでは通常通りのフライアウト(横に広がる)形式、モバイルでは画面を切り替えるような「スタック型」のサブメニューを実現できた。
また、一括操作バーの配置に関する課題もあった。Calendlyという製品では、画面の左側に常に表示される「サイドバー」がある。このサイドバーがあるため、メインコンテンツの表示領域が右にずれてしまう。初期の一括操作バーの実装では、画面の中央に固定するような配置だったため、サイドバーが出現すると、メインコンテンツに対して左に寄って見え、見た目のバランスが悪くなってしまった。
この問題を解決するために、「Outlet Pattern」というアプローチが採用された。これは、「ポータル」と組み合わせた賢い方法だ。まず、メインコンテンツが表示される領域に、目に見えない「受け皿(Outlet)」のようなコンポーネントを配置する。この受け皿は、常にメインコンテンツの表示領域の真ん中に位置するように調整されている。そして、本来は別の場所で定義されている一括操作バーのコンポーネントを、この「受け皿」の中に「移動させて表示する(ポータル)」のだ。この方法により、サイドバーがあるかないかに関わらず、一括操作バーは常にメインコンテンツに対して正しく中央に配置され、常に安定した見た目を保つことができるようになった。
さらに、再帰的に深くなるサブメニューの扱いも重要な課題だった。「再帰的」とは、メニューの中にメニュー、さらにその中にメニューと、何段階も深く続く可能性があるという意味だ。このような複雑な構造のメニューでも、ユーザーが迷うことなく操作できるように、フォーカスの管理やキーボードでの移動、そしてメニューの奥行きに応じた表示の切り替えが必要だった。開発者は、デスクトップではメニューが横に展開する「インラインフライアウト」、モバイルでは画面を切り替える「スタックオーバーレイ」という異なる表示方法を、メニューの深さやデバイスの種類に応じて動的に切り替える戦略を設計した。これにより、ユーザーはどのデバイスを使っても、深く階層化されたメニューをスムーズに操作できるようになっている。
今回の開発を通して得られた教訓は、小さく見えるUIコンポーネント一つでも、その開発はシステム全体のアーキテクチャに大きな影響を与えうる、ということだ。デザインシステム(UIコンポーネントのルールや部品の集まり)の制約の中で、柔軟かつ堅牢なソリューションを考えることが求められた。そして最も重要なのは、アクセシビリティは後から付け足すものではなく、コンポーネント設計の最初から基盤として考慮されるべきだという点だ。
一括操作バーの開発は、単に見た目をデザインするだけではなく、システムの構造、ユーザーがどのように操作するか、そして実際の製品が持つ制約など、多岐にわたる要素を考慮した、思慮深いコンポーネント設計の重要性を示す良い例となった。