Menubar
fandhe-frontend-pre-styled-ui の menubar mod が提供するスタイル済み Menubar 部品です。
複数の Menu を水平(または垂直)に並べるコンテナです。role="menubar" を持つルートの配下に、role="none" の Menu ラッパーと role="menuitem" のトリガーが並び、roving tabindex(フォーカスが常に 1 トリガーのみに当たる状態)の状態機械を提供します。Menubar 特有の挙動として、ある Menu が開いた状態でフォーカスを隣のトリガーへ移動すると、開く Menu も一緒に移動します。既存の Menu の anatomy はそのまま再利用せず、開閉状態機械・値語彙のみを再利用します。矢印キー・Home/End・typeahead による実際のフォーカス移動(DOM 配線)はクライアントランタイム(fandhe-frontend-wasm-full)が実装済みです。
関連 API: fandhe-frontend-pre-styled-ui API / fandhe-frontend-headless-ui API
Demo
headless-ui の Menubar(role="menubar")に pre-styled-ui の recipe CSS を適用した静的掲示です。File / Edit / View / Profiles の 4 Menu を水平配置し、開いている Menu を切り替えた 3 つの静的デモ(File Menu が open=Some(0)、View Menu が open=Some(2)、Profiles Menu が open=Some(3))を並べています。1 つ目(File Menu)は Item Group(Recent)・Separator・SubTrigger/SubContent(Export → PDF)の入れ子構造を含みます。roving tabindex(focused=0)により先頭の File トリガーのみ tabindex="0" です。Edit トリガーは highlighted=true とし、trigger の data-highlighted 配色(イシュー #1702)も掲示します。File Menu の report.md item は item-text + kbd(⌘O)の合成でショートカット表示を、Print… item は disabled=true として disabled_declarations 配色を掲示します(内部パート是正はイシュー #1703)。Export sub-trigger は右端に示唆グリフ(▸)のテキストノードを添え、サブメニュー示唆を表現します。2 つ目(View Menu)は checkbox-item 2 件(Status Bar が checked)、3 つ目(Profiles Menu)は radio-item-group + radio-item 3 件(Default が checked)をそれぞれ開いた状態で掲示し、item-indicator(末尾チェックマーク、イシュー #2034 で Themes 層へ CSS 付与)による checked 表現を確認できます(イシュー #2034、PR #2164 レビュー指摘対応)。
Features
- 複数 Menu を水平(または垂直)に並べるコンテナ。headless-ui 側(
fandhe_frontend_headless_ui::menubar)は Root / Menu / Trigger / Positioner / Content / Arrow / ArrowTip / Item / ItemText / ItemIndicator / ItemGroup / ItemGroupLabel / Separator / SubTrigger / SubContent / CheckboxItem / RadioItemGroup / RadioItem の 18 anatomy パーツを持つ(イシュー #1652 で参照突合し 11 → 18 パーツ)。Themes 側(本ページ)はイシュー #2034 で shadcn/ui と突合し、新設パートのうち item-text / item-indicator / checkbox-item / radio-item-group / radio-item の 5 パーツへSLOTS/CSS 付与を追いつかせた(#1528 が申し送っていた分の解消)。arrow / arrow-tip は shadcn/ui のデモに矢印インジケータが視認できないため意図的に未着装のまま。 - roving tabindex(focused/trigger_count/open/loop_focus/orientation の複合状態機械 Menubar)。フォーカス対象のトリガーのみ tabindex="0"、それ以外は tabindex="-1" になる。
- 開いている Menu を跨いだ左右移動: ある Menu が開いた状態で Next/Prev/First/Last/Focus アクションを送ると、フォーカス移動と同時に開く Menu も隣へ移る(menubar 特有の挙動、Toolbar の roving tabindex には無い)。
- menu パーツは role="none" を固定付与し、role="menubar" の子として menuitem/group 以外の要素を挟まないようにする(WAI-ARIA APG の menubar パターン)。
- サブメニューの開閉状態は Menubar 自身ではなく、呼び出し側が別途持つ Menu インスタンス(Disclosure 埋め込み)から SubTrigger/SubContent へ注入する。
- 既存の menu モジュールの anatomy はそのまま再利用しない(data-scope="menubar" を独自に持つ)。状態機械・値語彙(OpenState/aria/data-* ヘルパ)のみを再利用する。
Anatomy
root
menu
trigger
positioner
content
item-group
item-group-label
item
item-text
separator
sub-trigger
sub-content
checkbox-item
item-indicator
radio-item-group
radio-itemAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
orientation | Orientation | Orientation::Horizontal | root の role="menubar" に付与する向き(Horizontal/Vertical)。aria-orientation/data-orientation の両方へ反映される。 |
label | &str | — | root に付与する aria-label(空文字列のときは省略)。 |
focused | bool | — | trigger に付与。true のとき tabindex="0"、false のとき tabindex="-1"(roving tabindex)。 |
state | OpenState | — | trigger/positioner/content/sub_trigger/sub_content の開閉状態(Open/Closed)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
checkbox-item | data-state | checked, unchecked |
checkbox-item | data-value | status-bar, word-wrap |
content | data-state | closed, open |
item | data-disabled | (値なし) |
item | data-highlighted | (値なし) |
item | data-value | pdf, print, report.md |
item-indicator | data-state | checked, unchecked |
item-text | data-highlighted | (値なし) |
menu | data-state | closed, open |
positioner | data-state | closed, open |
radio-item | data-state | checked, unchecked |
radio-item | data-value | default, production, staging |
root | data-orientation | horizontal |
sub-content | data-state | closed |
sub-trigger | data-state | closed |
trigger | data-highlighted | (値なし) |
trigger | data-state | closed, open |
trigger | data-value | 0, 1, 2, 3 |
Examples
Keyboard shortcut suffix
shadcn/ui の Menubar デモが item 末尾に表示する ⌘T 風のキーボードショートカット表示に相当する合成パターンです。SlotRecipe は子孫セレクタを持たない(イシュー #708 で不採用確定)ため、新しい anatomy パートは追加せず、item の子として item_text(flex: 1 1 auto でラベルを引き伸ばす)と crate::kbd の kbd() を並べるだけで末尾寄せを実現しています(item 自身の CSS は変更していません)。
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| ArrowRight / ArrowLeft | 次/前のトリガーへフォーカスを移動する。ある Menu が開いていれば、開く Menu も追随する(MenubarAction::Next/Prev、wasm 層実装)。 |
| Home / End | 先頭/末尾のトリガーへフォーカスを移動する(MenubarAction::First/Last、wasm 層実装)。 |
| Enter / Space / ArrowDown | フォーカス中のトリガーの Menu を開く(MenubarAction::Open、wasm 層実装)。 |
| Escape | 開いている Menu を閉じる(MenubarAction::Close、wasm 層実装)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| role="menubar" / aria-orientation | root に付与。orientation 引数の値(horizontal/vertical)を反映する。 |
| role="none" | menu に付与。role="menubar" の子として menuitem/group 以外を挟まないための WAI-ARIA APG 慣行。 |
| role="menuitem" / aria-haspopup="menu" / aria-expanded | trigger/sub-trigger に付与。開閉状態(this Menu の state、もしくはサブメニュー側の sub_state)を反映する。 |
| role="menu" | content/sub-content に固定付与。aria-labelledby は labelledby 引数が Some のときのみ出力される。 |
| role="menuitem" | item に固定付与。disabled 時のみ aria-disabled="true" が付与される。 |
| role="group" | item-group に固定付与。labelledby が Some のときのみ aria-labelledby が付与される。 |