Accordion
高々 1 項目が開く single モードと、複数項目が同時に開く multiple モードの 2 状態機械を提供する開閉可能な項目リストです。fandhe-frontend-headless-ui の accordion mod は Root / Item / ItemTrigger / ItemIndicator / ItemContent の 5 anatomy パーツと、開閉状態を表す data-state・aria-expanded・aria-controls・(ラベル付き時のみ)role="region" を提供します。AccordionProps(orientation/disabled、イシュー #1636)を全パーツへ通すことで data-orientation を全パーツへ、全項目一括 disabled を項目単位の disabled と OR 合成した実効値として反映します。item-trigger は実効 disabled が true のときのみ aria-disabled="true" を、item-indicator は常時 aria-hidden="true" を付与します。キーボード操作(orientation に応じた ArrowDown/ArrowUp または ArrowRight/ArrowLeft・Home/End・非循環)の実 DOM 配線は fandhe-frontend-wasm-full の keynav.rs が担い、詳細は下記 Keyboard/Accessibility 節を参照してください。
スタイル済みの表示例は Accordion を参照してください。
関連 API: fandhe-frontend-headless-ui API
Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- 高々 1 項目が開く single モード(Accordion)と、複数項目が同時に開く multiple モード(MultiAccordion)の 2 状態機械を提供する(dispatch: select/deselect/toggle)。
- Root / Item / ItemTrigger / ItemIndicator / ItemContent の 5 anatomy パーツで構成される。
- item_trigger は type="button" を固定付与し、フォーム内配置時の意図しない submit を防ぐ。
- item_content は labelled_by が Some のときのみ role="region" + aria-labelledby をセットで付与し、名前なし region を作らない。
- AccordionProps(orientation/disabled、イシュー #1636)を全パーツへ通し、data-orientation を全パーツへ、実効 disabled(props.disabled || 項目単位 disabled)を item_trigger/item_indicator/item_content の data-disabled へ反映する。
- orientation の SSR 出力(data-orientation)に応じて fandhe-frontend-wasm-full がキーボード操作(vertical: ArrowDown/ArrowUp、horizontal: ArrowRight/ArrowLeft)を切り替える。フォーカス移動のみの循環しない実装(#582 の決定を維持)。
Anatomy
root
item
item-trigger
item-indicator
item-contentAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root/item/item_trigger/item_indicator/item_content: props | &AccordionProps | AccordionProps::default()(orientation: Vertical, disabled: false) | orientation(data-orientation として全パーツへ反映)と全項目一括 disabled(項目単位 disabled との OR 合成)。 |
item: state | OpenState | Closed | 項目の開閉状態(data-state へ反映)。 |
item: disabled | bool | — | 項目の disabled 状態(data-disabled へ反映)。 |
item_trigger: state | OpenState | Closed | 開閉状態(aria-expanded/data-state へ反映)。 |
item_trigger: disabled | bool | — | disabled 状態(実効 disabled はネイティブ disabled 属性・data-disabled・aria-disabled="true" の 3 つへ反映、イシュー #1636 で aria-disabled を追加)。 |
item_trigger: value | &str | — | 項目値。data-value へ出力し、wasm-full MAPPING_TABLE の "toggle" payload 契約として使う(イシュー #1127)。 |
item_trigger: id | Option<&str> | — | trigger 自身の id。 |
item_trigger: controls | Option<&str> | — | Some のとき aria-controls で item_content と関連付ける。 |
item_indicator: state | OpenState | Closed | 開閉状態のみを data-state へ反映する最小主義な装飾用パーツ。常時 aria-hidden="true" を付与する(イシュー #1636)。 |
item_indicator: disabled | bool | — | 実効 disabled を data-disabled へ反映する(イシュー #1636)。 |
item_content: state | OpenState | Closed | 開閉状態(closed のとき hidden 存在属性を付与)。 |
item_content: disabled | bool | — | 実効 disabled を data-disabled へ反映する(イシュー #1636)。 |
item_content: id | Option<&str> | — | item_trigger の controls と対で aria-controls 関連付けを成立させる。 |
item_content: labelled_by | Option<&str> | — | Some のときのみ role="region" + aria-labelledby をセットで付与する(名前なし region を作らないため)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
item | data-disabled | (値なし) |
item | data-orientation | vertical |
item | data-state | closed, open |
item-content | data-disabled | (値なし) |
item-content | data-orientation | vertical |
item-content | data-state | closed, open |
item-indicator | data-disabled | (値なし) |
item-indicator | data-orientation | vertical |
item-indicator | data-state | closed, open |
item-trigger | data-disabled | (値なし) |
item-trigger | data-orientation | vertical |
item-trigger | data-state | closed, open |
item-trigger | data-value | faq-0, faq-1, faq-2 |
root | data-orientation | vertical |
Examples
Disabled item
disabled な項目は item_trigger にネイティブ disabled 属性・data-disabled・aria-disabled="true" が付与され、item_indicator/item_content にも data-disabled が伝播します(イシュー #1636)。
Custom CSS
headless-ui は見た目を与えないため、data-scope/data-part/data-state/data-disabled/data-orientation セレクタのみで自前 CSS を当てます。
[data-scope="accordion"][data-part="item-trigger"][data-state="open"] {
font-weight: bold;
}
[data-scope="accordion"][data-part="item-trigger"][data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
[data-scope="accordion"][data-part="root"][data-orientation="horizontal"] {
display: flex;
}
セレクタは data-scope/data-part/data-state/data-disabled/data-orientation のみに依存します。
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Space / Enter | ネイティブ <button> の click 挙動経由で開閉する(fandhe-frontend-wasm-full の headless.rs::MAPPING_TABLE が "toggle" dispatch へ写像、イシュー #1127)。 |
| Tab / Shift+Tab | 全 item-trigger が tabbable(roving tabindex は適用しない、APG 仕様どおり)。 |
| ArrowDown / ArrowUp | orientation=vertical(既定)のとき、次/前の非 disabled item-trigger へフォーカス移動する。循環しない(実 DOM 配線は fandhe-frontend-wasm-full の keynav.rs::accordion_next_index_oriented)。 |
| ArrowRight / ArrowLeft | orientation=horizontal のとき、次/前の非 disabled item-trigger へフォーカス移動する。循環しない(イシュー #1636 で追加、実 DOM 配線は同上)。 |
| Home / End | orientation に関わらず先頭/末尾の非 disabled item-trigger へフォーカス移動する。循環しない(実 DOM 配線は同上)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-expanded | item_trigger に付与。項目の開閉状態(open で true)を表す。 |
| aria-disabled | item_trigger に付与。実効 disabled が true のときのみ "true" を付与する(イシュー #1636、ネイティブ disabled 属性の補完)。 |
| aria-controls | item_trigger に付与。controls が Some のとき対応する item_content の id を指す。 |
| aria-hidden | item_indicator に常時 "true" を付与する(イシュー #1636。開閉状態は item_trigger の aria-expanded から伝わるため、装飾用の indicator 自体は支援技術から隠す)。 |
| role="region" | item_content に付与。labelled_by が Some のときのみ aria-labelledby とセットで付与される。 |