Sidebar
アプリシェル用サイドバーに相当する shadcn/ui Sidebar 部品です(参照軸はイシュー #2001、shadcn/ui 追加はイシュー #2004)。fandhe-frontend-headless-ui の sidebar mod が構造・アクセシビリティ(WAI-ARIA)・表示状態(data-*)のみを提供する unstyled 部品で、provider / root / header / content / footer / separator / input / group / group-label / group-content / group-action / menu / menu-item / menu-button / menu-action / menu-badge / menu-sub / menu-sub-item / menu-sub-button / rail / trigger / inset の 22 anatomy パーツを持ちます。
nav_list(menu/menu-item/menu-button の構造・aria-current 語彙)・collapsible(menu-sub の開閉は呼び出し側が合成する)・tooltip(menu-button の describedby が aria-describedby のみで関連付けを表す)の既存語彙を再利用し、新規の意味論は持ち込みません。Sidebar 状態機械は data-state="expanded"|"collapsed" を管理します。
アクセシビリティ
rootはnavでlabel(aria-label)が必須引数です。divへのaria-labelは支援技術に露出しないため、ランドマークが必要な本部品では型でアクセシブルネームを強制します。provider/rootはdata-state/data-collapsible/data-variant/data-side(mobile 時のみdata-mobile)を固定出力します。data-collapsibleは状態に関わらず常に出力します(SSR 決定性優先の意図的差分)。menu-button/menu-sub-buttonはhrefがSomeのときa、Noneのときbutton type="button"を描画し、activeのときのみdata-active+ (aのときのみ)aria-current="page"を付与します。groupはrole="group"を固定出力し、labelledbyがSomeのときのみaria-labelledbyを併記します(group-labelのidが対になります)。menu-subは開閉状態を持たない静的なulです。開閉が必要な場合は呼び出し側でcollapsible::root/trigger/contentを合成します(他 scope を内包しない設計)。triggerはaria-expanded/aria-controls(controlsがSomeのとき)を持つキーボード操作可能な開閉ボタン、railはtabindex="-1"のマウス専用領域です。insetはdivです(mainではありません。docs サイトのページ骨格が既にmainを描画しているため、role="main"が必要な利用者はattrsで明示的に渡します)。menu-skeleton(ローディング装飾)は本層に含めません。fandhe-frontend-pre-styled-ui側(後続イシュー #2073)の責務です。- Cmd/Ctrl+B のショートカット・モバイル drawer 切替・
menu-buttonの tooltip hover 配線の実 DOM 配線は本層の範囲外です(fandhe-frontend-wasm-fullの後続責務、#2074)。
自前 CSS の最小例:
[data-scope="sidebar"][data-part="provider"][data-state="collapsed"] {
width: 3rem;
}
[data-scope="sidebar"][data-part="menu-button"][data-active] {
background: #eef;
}
[data-scope="sidebar"][data-part="rail"] {
cursor: col-resize;
}fandhe-frontend-pre-styled-ui に対応するスタイル済み部品があります。Themes 版は Sidebar を参照してください。
関連 API: fandhe-frontend-headless-ui API
Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- アプリシェル用サイドバー(shadcn/ui Sidebar 相当)。Provider / Root / Header / Content / Footer / Separator / Input / Group / GroupLabel / GroupContent / GroupAction / Menu / MenuItem / MenuButton / MenuAction / MenuBadge / MenuSub / MenuSubItem / MenuSubButton / Rail / Trigger / Inset の 22 anatomy パーツを持つ(sidebar.rs モジュール doc)。
- Provider/Root は Sidebar 状態機械(data-state="expanded"|"collapsed")+ 静的 SidebarProps(data-collapsible/data-variant/data-side、mobile 時のみ data-mobile)を固定出力する。data-collapsible は状態に関わらず常時出力する(SSR 決定性優先の意図的差分)。
- MenuSub の開閉は状態を持たない静的な ul であり、開閉が必要な場合は呼び出し側が collapsible::root/trigger/content で合成する(他 scope を内包しない設計、Examples 参照)。
- MenuButton/MenuSubButton は href の有無で a/button type="button" を切り替え、active 時のみ data-active + (a のときのみ)aria-current="page" を付与する(nav_list の current 語彙を踏襲)。
- Inset は div(main ではない)。docs サイトのページ骨格が既に main を描画しているため、文書内の非 hidden main が 2 個になる HTML 制約違反を避ける意図的差分(role を予約しないため呼び出し側が attrs で role="main" を渡せる)。
- menu-skeleton(ローディング装飾)は本層に含めない。shadcn/ui 実装はランダム幅で SSR 決定性を壊すため、docs/policy/intentional-non-adoption.md §3.25 規則 2 により pre-styled-ui 側(#2073)の責務とする。
- Cmd/Ctrl+B のキーボードショートカット・モバイル drawer 切替・MenuButton の tooltip hover 配線は fandhe-frontend-wasm-full の後続責務(#2074)。
Anatomy
provider
root
header
content
input
separator
group
group-label
group-action
group-content
menu
menu-item
menu-button
menu-action
menu-badge
menu-sub
menu-sub-item
menu-sub-button
footer
rail
trigger
insetAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
provider/root(state, props) | &Sidebar, &SidebarProps | — | Sidebar 状態機械と静的 props から 5 種の data-* を導出する。 |
root(label, id) | &str, Option<&str> | — | label は必須の aria-label(div への aria-label は無効なため nav + 必須ラベルで型強制)。id は Some のとき trigger の aria-controls と対にする。 |
menu_button/menu_sub_button(props) | &SidebarMenuButtonProps / &SidebarMenuSubButtonProps | — | href が Some なら a、None なら button type="button"。active/size/variant/describedby を持つ。 |
group(labelledby) / group_label(id) | Option<&str> | — | group は role="group" 固定 + labelledby が Some のときのみ aria-labelledby。group_label の id が対になる。 |
rail(state, label) / trigger(state, label, controls) | &Sidebar, &str, Option<&str> | — | rail は tabindex="-1" のマウス専用領域。trigger は aria-expanded/aria-controls を持つキーボード操作可能な開閉ボタン。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
menu-button | data-active | (値なし) |
menu-button | data-size | default |
menu-button | data-variant | default |
menu-sub-button | data-active | (値なし) |
menu-sub-button | data-size | sm |
provider | data-collapsible | offcanvas |
provider | data-mobile | (値なし) |
provider | data-side | left |
provider | data-state | collapsed, expanded |
provider | data-variant | sidebar |
rail | data-state | expanded |
root | data-collapsible | offcanvas |
root | data-mobile | (値なし) |
root | data-side | left |
root | data-state | collapsed, expanded |
root | data-variant | sidebar |
trigger | data-state | collapsed, expanded |
Examples
collapsible の合成による MenuSub の開閉
sidebar は開閉状態を持たない静的な menu-sub を提供し、開閉が必要な場合は呼び出し側で collapsible::root/trigger/content を合成します(他 scope を内包しない設計)。
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Tab / Shift+Tab | ネイティブ a[href]/button の Tab 順序でフォーカス移動する(rail は tabindex="-1" のためフォーカス対象から除外される)。 |
| Enter / Space | trigger/menu-button/menu-action 等のネイティブ button/a の既定動作で発火する。 |
| Cmd/Ctrl+B(配線は範囲外) | shadcn/ui のショートカット。headless 層は静的マークアップのみを提供し、実 DOM 配線は fandhe-frontend-wasm-full の後続責務(#2074)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-label | root(必須、nav ランドマークのアクセシブルネーム)/ rail・trigger・group-action・menu-action(必須、アイコンのみの操作ボタン)に付与する。 |
| aria-expanded / aria-controls | trigger が Sidebar の展開状態を反映し、controls が Some のとき root の id と対で関連付ける。 |
| aria-current="page" | menu-button/menu-sub-button が a(href 指定)かつ active のときのみ付与する(button のときは付与しない)。 |
| aria-labelledby / aria-describedby | group が labelledby(group-label の id)と対、menu-button の describedby は呼び出し側が tooltip と関連付けるためのスロット。 |
| role="group" | group のみに固定付与する(shadcn の role="list" からの意図的差分、item::group と同型の判断)。 |