Navigation Menu
トリガーのクリックで開くナビゲーションパネル(高々 1 項目のみ開く)です。fandhe-frontend-headless-ui の navigation_menu mod は Root / List / Item / Trigger / ItemIndicator / Content / Link / Indicator の 8 anatomy パーツを提供する unstyled 部品であり、Themes 版と異なりスタイル(CSS)は一切持ちません。nav_list(ディスクロージャなしの静的リンク集)とは、開閉状態機械の有無で使い分けます。ルートレベルの indicator(開いている Trigger の下でスライドするポインタ)は root 直下・list の兄弟に置く装飾パーツで、aria-hidden="true" と data-state(開いている項目が 1 つでもあれば open)・data-orientation・data-value(開いている項目値、Some のときのみ)を出力します。style 属性は出力しません(座標追従・CSS 変数命名は上層の責務、下記参照)。
NavigationMenuProps { orientation }(既定 Horizontal)を root / list / item / content へ渡すと data-orientation が出力され、item / content は value を data-value として出力します。本部品は SSR での属性出力と状態機械のみを担い、click → dispatch 配線・キーボード操作・Escape キーでの閉鎖は fandhe-frontend-wasm-full が実 DOM 配線を担います。
キーボード操作
| キー | 対象 | 効果 |
|---|---|---|
| Enter / Space | Trigger | claim しません(ネイティブ <button> の click → "toggle" dispatch)。 |
ArrowRight / ArrowLeft(orientation="horizontal")、ArrowDown / ArrowUp(orientation="vertical") | Trigger | Trigger 間のフォーカスを移動します(disabled をスキップ、既定は循環なし。data-loop-focus="true" で循環)。 |
| Home / End | Trigger | 先頭 / 末尾の非 disabled Trigger へフォーカスします。 |
ArrowDown / ArrowUp(orientation="horizontal")、ArrowRight / ArrowLeft(orientation="vertical") | Trigger | closed なら click を合成して開き先頭 / 末尾リンクへ、open なら合成なしで先頭 / 末尾リンクへフォーカスします。 |
| ArrowDown / ArrowUp / ArrowRight / ArrowLeft / Home / End | Content 内 Link | 同一 Content 内の非 disabled リンク間を非循環で移動します。 |
| Escape | open 中の Trigger / Content 内 Link | click を合成して閉じ、Trigger へフォーカスを戻します(closed の Trigger 上は no-op)。 |
| Tab / Shift+Tab | — | 配線はありません(roving tabindex 不採用、全ボタン・リンクがタブ順に残ります)。 |
参考サイトとの差分
ark-ui NavigationMenu・Radix Primitives Navigation Menu と突合し、ItemIndicator パートを新設(6 → 7 anatomy パーツ)、NavigationMenuProps による data-orientation(root/list/item/content)、data-value(item/content)を追加し、各パーツ関数の呼び出し側 attrs から固定属性キーの偽装を除去する drop_reserved を追加しました。ルートレベルの Indicator(7 → 8 anatomy パーツ)も新設し、Radix の「構造 + 装飾 + 実測を 1 パーツで担う」設計とは異なり、構造 + data-state のみを本層で担い、着装は fandhe-frontend-pre-styled-ui、実座標の計測は fandhe-frontend-wasm-full の責務に分離しました。Radix は List を div で包んで Indicator を track の兄弟に置きますが、本モジュールの list は素の <ul> のため Indicator は root 直下・list の兄弟に置きます。一方、以下は意図的に合わせていません。
- Viewport / ViewportPositioner / Arrow: レイアウト計測を伴う装飾関心のため headless 層には持ち込みません(
docs/policy/intentional-non-adoption.md§3.25 規則 2)。 - Sub(入れ子ナビゲーション): 状態機械の入れ子は未実装です。
- hover / delay による自動 open・open-follows-focus・typeahead: クリック起点の開閉のみをサポートし、ホバーでの自動展開は実装しません。
data-trigger-proxy-id(ark-ui): 実行時 proxy 要素向けの内部属性のため不採用です。- Radix の
data-active(link): ark-ui 語彙のdata-currentへ統一しています。 data-motion: viewport 寸法測定と同様、装飾・アニメーション関心のため未実装です。
スタイル済みの表示例は Navigation Menu を参照してください。
関連 API: fandhe-frontend-headless-ui API
自前 CSS の最小例
Themes 版を使わず本部品を直接使う場合、[data-scope="navigation-menu"][data-part="..."] セレクタでスタイルを当てます。content には [hidden] ガードを必ず含めます(closed のとき hidden 存在属性が同一フレームで即時付与・除去されるため、CSS トランジションは開閉どちらの向きにも発火しません)。
[data-scope="navigation-menu"][data-part="content"][hidden] {
display: none;
}
[data-scope="navigation-menu"][data-part="trigger"][data-state="open"] {
font-weight: 600;
}
[data-scope="navigation-menu"][data-part="link"][data-current] {
text-decoration: underline;
}
[data-scope="navigation-menu"][data-part="item"][data-disabled] {
opacity: 0.5;
}Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- トリガー起点で開閉するナビゲーションパネル。Root / List / Item / Trigger / ItemIndicator / Content / Link / Indicator の 8 anatomy パーツを持つ(navigation_menu.rs モジュール doc)。
- 高々 1 個の Trigger だけが開く状態機械(SingleSelect を埋め込んだ NavigationMenu、dispatch は "select"/"toggle"/"deselect")。
- role は一切付与しない。root は素の nav の暗黙 ARIA role(navigation)に依拠し、role="menu"/role="menuitem" は付与しない(nav_list と同じ判断、文書ナビを操作メニューと誤伝達しないための設計)。
- data-motion(アニメーション方向の露出)・viewport 寸法測定は実装しない(intentional-non-adoption.md §3.25 規則 2 により headless 層へ持ち込まない設計判断、module doc「data-motion・viewport 測定を実装しない」節)。
- indicator(イシュー #2187)はルートレベルの装飾パーツ(root 直下・list の兄弟)で、開いている Trigger の下でスライドするポインタを表す。構造 + data-state のみを本層が担い、着装(CSS 変数)は pre-styled-ui、実座標の計測は wasm-full の責務(#2208/#2209 系の後続)。
Anatomy
root
list
item
trigger
item-indicator
content
link
indicatorAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root(label) | &str | — | root(nav)へ付与する aria-label(必須引数)。 |
trigger(state) | OpenState | — | 項目の開閉状態。aria-expanded/data-state へ反映される。 |
link(current) | bool | false | true のとき aria-current="page"+data-current を出力する。 |
indicator(state, value) | (OpenState, Option<&str>) | — | ルートレベルの装飾パーツ。value は Some のときのみ data-value として出力(開いている項目値を構造情報として伝える)。state が Closed のとき hidden を付与する。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
content | data-orientation | horizontal |
content | data-state | open |
content | data-value | products |
indicator | data-orientation | horizontal |
indicator | data-state | open |
indicator | data-value | products |
item | data-disabled | (値なし) |
item | data-orientation | horizontal |
item | data-state | closed, open |
item | data-value | docs, enterprise, products |
item-indicator | data-orientation | horizontal |
item-indicator | data-state | open |
item-indicator | data-value | products |
link | data-current | (値なし) |
list | data-orientation | horizontal |
root | data-orientation | horizontal |
trigger | data-disabled | (値なし) |
trigger | data-state | closed, open |
trigger | data-value | docs, enterprise, products |
Examples
全項目 closed の初期表示
SSR の初期描画時点を想定し、すべての Trigger/Content を closed 状態にした構成です。
Accessibility
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-expanded / aria-controls | trigger に付与。開閉状態と content との関連付け(controls が Some のときのみ)を表す。role は付与しない。 |
| aria-labelledby | content に付与(labelled_by が Some のときのみ)。role は付与しない。 |
| aria-current="page" | link に付与(current が true のときのみ)。role は付与しない。 |
| aria-hidden="true" | indicator に常時付与。装飾用の視覚要素であり、支援技術へは trigger の aria-expanded から開閉状態が既に伝わる。 |