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 はそのまま再利用せず、開閉状態機械・値語彙のみを再利用します。矢印キーによる実際のフォーカス移動(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 の 2 Menu を水平配置し、File Menu を開いた状態(open=Some(0))で表示しています。Item Group(Recent)・Separator・SubTrigger/SubContent(Export → PDF)の入れ子構造も含みます。roving tabindex(focused=0)により先頭の File トリガーのみ tabindex="0" です。
Features
- 複数 Menu を水平(または垂直)に並べるコンテナ。Root / Menu / Trigger / Positioner / Content / Item / ItemGroup / ItemGroupLabel / Separator / SubTrigger / SubContent の 11 anatomy パーツを持つ。
- 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
separator
sub-trigger
sub-contentAPI 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 |
|---|---|---|
| content | data-state | open |
| item | data-highlighted | |
| item | data-value | pdf, report.md |
| menu | data-state | closed, open |
| positioner | data-state | open |
| root | data-orientation | horizontal |
| sub-content | data-state | closed |
| sub-trigger | data-state | closed |
| trigger | data-state | closed, open |
| trigger | data-value | 0, 1 |
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 が付与される。 |