🐹

MenuとPanelの見極め方

2024/02/29に公開

ニコニコ生放送でフロントエンドを担当している misuken です。

今回はとあるPull Requestを発端として、MenuPanel の違いやその関係性を明らかにするため、一歩ずつ分析を進め、最終的に多角的な分析で高精度の結論に達した考察の過程を共有します。

コンポーネント設計やコンポーネント名を明らかにするときの参考になれば幸いです。

2024-03-11追記: 記事タイトルを変更しました

前提

この記事は BCD Design を基礎とし、以下の記事で紹介した理論を踏まえた内容となっていますが、記事中にリンクが貼られているので、適宜参照しながら読み進めてみてください。

気付きの発端

ある日の Pull Request

BCD Design の Base のディレクトリに以下のような構成になる RadioGroupMenu というコンポーネントを追加するPull Requestのレビュー依頼が来ました。

// このような構成になるコンポーネント
<div>
  <RadioGroup />
</div>

イメージ画像

PullRequestのRadioGroupMenuのイメージ

これを見て、所感として以下が浮かびました。

  • Menu は本来 Item と組み合わさった <ul> <li> 形式の型(または aria でそれ相当)であると考えられるので何かおかしそう
  • RadioGroupMenuMenuMenu と言っているように冗長に感じられる
  • この構成の場合 Menu ではなく RadioGroup を持つ Panel なので RadioGroupPanel となりそう

このコンポーネントは浮遊して表示されるものでもあったので、RadioGroupMenu のように UI(RadioGroup) + UI(Menu) のコンポーネントとして素直に考えると、RadioGroupPanel に組み合わせた RadioGroupPanel と表現したほうが適していると考えられます。

RadioGroupMenu の利用先

RadioGroupMenu は新着順、更新順などの並び順を選ぶための OrderMenu というコンポーネントで使用されていました。(サイトが注文を扱うような場合は Order よりも SortOrder を使用したほうが良いでしょう)

RadioGroupPanel に変われば OrderMenuOrderPanel に変わることになりますが、OrderPanel だと若干の言葉足らず感が否めません。

OrderPanel を日本語に置き換えてみると "並び順パネル" であり、"並び順メニュー" や "並び順メニューパネル" のほうがまだしっくりきてしまいます。

理由を考えてみると、ここでメニューが指すのは Menu というUIの型ではなく "選択できるもの" という意図だと受け取れます。

そこで menu の単語の意味を調べてみると、以下あたりにしっくりくる表現があります。

2.《コ》メニュー◆ユーザーが利用可能なオプションのリスト。
3.〔利用可能なものの〕一覧、メニュー

つまり、選べる(利用可能)ということが読み取れれば良いので、例えば OrderSelectPanel "並び順選択パネル" などでも意図が表現できるわけです。

拡張性の問題

並び順を選ぶという具体的な目的が見えてきたところで、コンポーネントの拡張性に関しても考えてみます。

これまでの流れで、UIの単位としては RadioGroupMenu よりも RadioGroupPanel のほうが適切であると述べましたが、実際は RadioGroupPanel という単位でコンポーネントにする価値はほとんどありません。

RadioGroupPanel というコンポーネント名は、以前の記事に書いた "部品Aを利用するB" に該当しますが、 "RadioGroup を利用する Panel" を定義しようとしても、BCD Design の Base の段階では RadioGroup を一つまたは複数置けるようにしておくことしかできません。

さらに、そのコンポーネントを利用する際に他の表示要素を追加したくなると、無理に RadioGroupPanel を使ってレイアウトの制約を受けるより、新たに RadioGroupPanel を組み合わせて自由に作ったほうがスムーズであるためです。

パネルで決まることは少ない

コンポーネント名を明名するときに考えたことで扱っていた Field というコンポーネントの話を思い出してみます。

Field コンポーネントとの比較

Field のときは、ラベル、メッセージ、必須表現等、一般的にそれ自体が持つ構成がある程度はっきりしていて、あとは「どのような入力UIと連携するか?」という限られた部分だけが抽象化されていました。

しかし Panel は内容の部分が自由であり、Panel という名前によって決まる部分が少ない違いがあります。
Panel で決まるのはだいたい以下で、それ以上の構成は具体的な関心と結び付いたときに決まります。

  • パネルとしての土台がある
  • 閉じるボタンの有無

つまり、これ以上の構成を含む XxxPanel を作る時点で、必ず関心への依存が発生することを意味します。

関心の名前を探る

関心への依存が発生するということは、コンポーネント名にその依存を表す単語を含めることになるので、RadioGroup というUI名ではなく、 RadioGroup を含める必要が生じた理由を関心の視点から捉えてみます。

それは "並び順を選択したい" という理由ではあるのですが、"選択する" という表現がちょっと具体的すぎる感じがするので、もう少し汎用性の高いスコープのイメージで漠然と思考を巡らせると "並び順に関する設定を行えるもの" といった表現が浮かんできます。

ここで "設定" という単語が出てきたのでこれを当てはめてみましょう。

OrderSelectPanel よりも OrderSettingPanel のほうがよりピントの合った印象になります。

例えば、そこに "設定を記憶する" のようなチェックボックスを置くような拡張を行う場合も OrderSettingPanel のほうが馴染みます。

OrderSettingPanel は設定内容が "並び順" に限定されているだけで、一般的な SettingPanel の概念と一致するため、この方向性の精度は高いと言えます。

設定パネルという切り口

それでは設定パネルの切り口から考えてみます。

ここではイメージしやすいように、具体的な関心名として "番組" Program を使います。

設定パネルとして組み立てる

具体的な関心 ProgramOrderSetting において Panel を利用する場合、"関心Aで利用するB"" に該当するので ProgramOrderSettingPanel になります。 日本語では "番組並び順設定パネル" になります。

名称 日本語 BCD Design の分類
Program 番組 Domain
OrderSetting 並び順設定 Common
Panel パネル Base

そこそこ精度が上がってきたのですが、並び順の設定が行える場合、このコンポーネントの成長軸を考慮すると、並び順に限らずフィルタ条件のような要求はありがちです。 そこで、"一覧" に関する設定を行えるような成長軸も意識してみます。

するとこれまで "一覧" という意味を表す単語がコンポーネント名から欠けていたことに気付きます。

たしかに並び順は単一の番組自体にかけているわけではなく、番組の一覧(一覧にするとき)にかけているので ProgramListingOrderSettingPanel のほうが正しかったということになります。

名称 日本語 BCD Design の分類
Program 番組 Domain
ListingOrderSetting 一覧並び順設定 Common
Panel パネル Base

その上で、並び順以外の設定も含められるように Order の縛りを外してスコープを広げると、 ProgramListingSettingPanel という名前になります。

名称 日本語 BCD Design の分類
Program 番組 Domain
ListingSetting 一覧設定 Common
Panel パネル Base

ProgramListingSettingPanel は、一覧に関する設定全般を含められるスコープになっているので、番組の一覧設定で使用される設定項目を全部詰め込んでおいて、使用する場所で必要な設定項目だけ表示すると効率的であることが見えてきます。(ある場所では A と B、他の場所では B と C の設定項目を使用する場合があるため)

番組コマンドパレットの例

ここでニコニコ生放送の例を挙げましょう。

ニコニコ生放送にはプレーヤーの番組コメント投稿フォームのコマンド入力欄にフォーカスすると表示される、番組コマンドパレットというコンポーネントがあります。

ニコニコ生放送のコマンドパレット

構成は以下のようなもので、ProgramCommandPalette は言い換えると ProgramCommandSettingPanel を表していると言えます。しかし、少し前にコメント投稿に関する設定も追加されたので、ProgramCommentPostSettingPanel にリネームしていったほうが適切であることもわかります。

  • コメントの大きさの設定 (実装は RadioGroup)
  • コメントを流す位置の設定 (実装は RadioGroup)
  • コメントの色の設定 (実装は RadioGroup)
  • コメントの投稿設定 (実装は ToggleButtonField 将来的に SwitchField に変更予定)
  • 特定の条件を満たしたときに表示されるリンク動線(画像には表示されていません)

このコンポーネントは内部に RadioGroup を含んでいますが、RadioGroupPanel を拡張した延長線上には存在しません。

Panel 内の構成は "番組コメント投稿設定" という関心に依存して決定されていると言えます。

UI 視点からの分析

次に UI の視点から MenuPanel の違いや、関係性に関して分析してみます。

UI としての Menu、つまり末尾が Menu で終わるコンポーネントは、以下を満たしていると明確になります。

  • コンポーネント自体が Menu というUIそのものである
  • コンポーネントのルートの要素が <ul> または role="menu" である

React SpectrumMenu はariaを上手に使ってセクションや見出しを加えながらも Menu の型を保っていると言えます。(コンポーネントのルートとなる要素が role="menu" になっているため)

Panel

UI としての Panel、つまり末尾が Panel で終わるコンポーネントは、以下を満たしていると明確になります。

  • コンポーネント自体が Menu というUIそのものではない
  • 関心と組み合わさるまで構成が決まらない

MenuPanel はベースの見た目が同じことがあるので、Panel をベースに使った Menu を作れるようにしておくと便利です。

実現方法は色々ありますが、例えば以下のようなイメージになります。

この場合、コンポーネントの型としては Menu になります。

// Panel をベースに使った Menu の例
<Panel as={Menu}>
  <Item>A</Item>
  <Item>B</Item>
  <Item>C</Item>
</Panel>

型に収まらないメニュー

ときには Menu にも Panel にも収まらないメニューが存在します。

例えば、銀行やクレジットカード、ショッピングサイトでメニューを開くと表示される、複数のメニュー等で構成された複合的なUIです。

このようなものには以下のように対処していきます。

  • ネストした Menu で表現できるなら Menu で表現する
  • ネストした Menu で表現できないなら MenuPanel で表現する

MenuPanel は Base に抽象的なコンポーネントとして作成しておくことはできません。
なぜなら、Menu を部品として使用することはわかっていても、何らかの文脈のある関心と組み合わさるまで構成が決められないからです。

そのため、名前が MenuPanel で終わるコンポーネントは、具体的な関心名と組み合わさるタイミングで始めて、 Common や Domain に誕生することになります。

ユースケースの観点

ユーザーはメニューかパネルかといった部分を意識しないので、ユースケースの観点から問題にならないかどうかを考えてみます。

メニューを開くというユースケースにおいて、実際にはパネルを開くことにはなりますが、メニューを開くためのボタンのテキスト(操作の意味を表す文言)は "メニューを開く" 等になるはずで、パネルの中にメニューも包括されているので、結果的にメニューは開けていることになり、適切に表現できていると言えます。

実装時の観点

実装時にメニューを探してしまい、パネルを探せないという問題があるかどうかを考えてみます。

コンポーネント名の関係上、対象の XxxMenu を探すときに、アルファベット順でもコード補完でも XxxMenuPanel が見つかるので問題ありません。

日本語の視点から分析

ここでは日本語の視点を加えることで、さらに理解を深めていきます。

Menu は日本語で "一覧" を表します。

ただし Menu には "利用可能なものの" という意味が含まれるため、単なる一覧であるならば List で表現されるべきということがわかります。

このあたりの使い分けは、HTMLやariaのレベルでも同様のことが書かれており、単語の意味に対して忠実であることがわかります。

Panel

Panel は "パネル" ですが、"パネル" は英語です。
ちゃんと日本語の漢字に翻訳すると "板" や "盤" になります。

"板" と "盤" の違いをAIに聞いてみたところ、要約すると以下のような回答が返ってきました。

意味
何かに加工するための材料
特定の用途で使用された加工済みのもの

UIの世界で言う Panel は未加工の板ではなく、切り出して整形され、ページを構成する部品として扱えるものなので "盤" のほうが当てはまります。

また、 "盤" には "ものを乗せる台" としての意味もあるため、他のUIを乗せる台としての役割も一致します。

boardとしての "盤"

将棋盤やチェス盤のように、ボードゲームの盤面を表す場合も "board" という単語が使われます。

これについてもAIに聞いてみたところ、"ものを乗せる台" としての意味の他にゲームの "舞台" としての意味を持っているといった回答が返ってきました。

SettingPanel

Panel が "盤" であるなら SettingPanel は "設定盤" になります。

Panel が "盤" としてどのように使用されるか調べてみると(alc で "panel 盤" を検索) "配電盤" や "操作盤" など色々な "◯◯盤" が出てきます。

すると "設定盤" はちょっとおかしな名前に見えてきます。

"設定"(setting) という単語は名詞であり、 BCD Design の処理される対象(名詞)と処理自体(動詞) の観点では処理される対象になります。

しかし、 "◯◯盤" の "◯◯" にはだいたい処理自体を表せる単語が並んでいることがわかります。

  • ✅ 操作盤 console panel → console
  • ✅ 配電盤 (power) distribution panel → distribute
  • ✅ 給電盤 (power) feeder panel → feed
  • 🤔 設定盤 setting panel → set? setup? configure?

たしかに、"設定盤" だと設定をどうするのかが説明されていないため、名前に若干の言葉足らず感があります。
このことから本質的には "設定◯◯盤" となるであろうことが推察できます。

そこで、改めて "panel 盤" で検索した結果 を眺めてみると、まさにそれそのものを表す項目がありました。

"制御盤" です。

panelと盤の検索結果

WindowsのOSでいうところのコンパネ(ControlPanel)もまさにそれです。単語の意味を適切に扱っていくと、思わぬところで別のものとぴったり適合するのが面白いところです。

つまり "設定制御盤" SettingControlPanel がそれを最も正確に表す名前であると言えます。たしかにこれであれば日本語でも名称と意味の間に違和感はありません。

  • "番組一覧設定制御盤" ProgramListingSettingControlPanel
  • "番組一覧並び順設定制御盤" ProgramListingOrderSettingControlPanel
名称 日本語 BCD Design の分類
Program 番組 Domain
ListingOrderSetting 一覧並び順設定 Common
Control 制御 Case
Panel Base

実際のところ一般的には "設定" に制御の文脈も含んでいるようなものなので SettingControlPanel ではなく SettingPanel を使っても問題ないでしょう。

このように本質を理解することで全体像をしっかり理解でき、他の設計をするときにも役立つので、頭の引き出しを増やすことに繋がります。

◯◯盤の総称

少し横道にそれますが、"配電盤" でググってみると "分電盤" "制御盤" などの用語が並んでいるページが見つかります。

そこではそれらの意味を解説しており、それらは "装置" や "設備" と書かれていました。

そこで "装置" と "設備" は何が違うのか気になったので "装置とは" "設備とは" でググってみたところ、以下の結果が表示されました。

"装置とは?"の検索結果

"設備とは?"の検索結果

要するに "装置" は機械的なもので、備え付けられる対象を意味し、"設備" は装置などが備え付けられたものを意味します。

つまり "設定制御盤" は機械として見れば "設定制御装置" であり、ページに備え付けられたものとして見れば "設定制御設備" であると言えます。

このように現実世界とも整合性が合うことは、高い精度でUIの本質を表現できていることの裏付けと言えます。

さて、全容が明らかになってきたところで、冒頭のほうで MenuMenu がおかしいと書いた部分もスッキリさせてしまいましょう。

以前 共通部分をスマートに管理するディレクトリ構成 で書かれたいたように、 TextBoxField のようなUI名 + UI名で表現されるコンポーネントの場合、Field の中の入力部分が抽象化され、そこに具体的な TextBox を連携させることで成立していると紹介しました。

名称 日本語 BCD Design の分類
TextBox テキストボックス(文字列入力機能) Base
Field フィールド(欄) Base

これに Menu を当てはめてみましょう。もし ButtonMenu が存在した場合、メニューの項目の部分が抽象化されていて、そこに具体的な Button を連携させることで成立していることがわかります。当然 LinkMenu なら Link と連携することになります。

ButtonMenuとLinkMenuのイメージ

その前提でいくと、 RadioGroupMenu にした場合、一つの項目ごとに RadioGroup が連携されることを意味してしまうので、これは意図した形ではありません。

RadioGroupMenuのイメージ

もし、一つの項目に一つのラジオボタンが連携されることを想定しているのであれば、 RadioMenu になるべきです。

RadioMenuのイメージ

すると RadioMenu 自体が RadioGroup 相当の単位であることがわかり、MenuGroup の部分がどちらも複数項目を束ねる存在である点で一致します。

MenuとGroupの共通項

これが RadioGroup は実質 RadioMenu 相当で、 RadioGroupMenu にすると RadioMenuMenu になり、冗長になると感じた正体だったということになります。

まとめ

RadioGroupMenu を発端として様々な視点で分析を行った結果、まさかのWindowsのコンパネや、現実世界とも整合性が合うなど、想像以上に広い範囲と繋がっていることに気付くことができました。

単語の意味を知り、適切な単語を選択することは単語自体が持つ意味の型を利用できる絶大な有益性があると考えています。

今回の記事の主なポイントは以下。

  • Menu と Panel の違いを認識する
  • 入力UIを含んでいる場合は SettingPanel の筋を考えてみる
  • 複合的なメニューは MenuPanel を検討する

物事を明らかにするときに大切なことは次の通りです。

  • 多角的な視点からそのものが何なのかを考える
    • 視点を切り替えても概念が一致すること
  • 対称性を意識する
    • 単語を取り替えたときにも概念が一致すること
  • AI や検索を利用する
    • AIに単語 A と B の違いについて尋ねてみる
    • "◯◯とは" でググってそれは何なのかを調べてみる

おまけ

記事を書いている途中に、ふと zenn のヘッダーのUIの名前が気になって見てみたところ、ちゃんとメニューとパネルが使い分けられていたので、本質を追求すると自然と名前が一致することの面白さを感じました。

ユーザーメニュー 通知パネル
zennのメニュー zennのパネル

参考

株式会社ドワンゴでは、様々なサービス、コンテンツを一緒につくるメンバーを募集しています。 ドワンゴに興味がある。または応募しようか迷っている方がいれば、気軽に応募してみてください。

Discussion