Popover
トリガー起点のオーバーレイです。fandhe-frontend-headless-ui の popover mod は Root / Trigger / Anchor / Positioner / Arrow / ArrowTip / Content / Title / Description / CloseTrigger / Indicator の 11 anatomy パーツを提供します。trigger は aria-haspopup="dialog"・aria-expanded・(controls が指定されたときの)aria-controls を持ち、content は role="dialog" を固定付与します。本部品は SSR での属性出力と状態機械のみを担い、trigger/close-trigger の click → dispatch 配線・Escape キーでの閉鎖・外側クリックでの閉鎖は fandhe-frontend-wasm-full が実 DOM 配線を担います。content は tabindex="-1" を固定付与します(プログラム的フォーカスのみを許可する WAI-ARIA dialog パターンの前提)。
キーボード操作
| キー | 対象 | 効果 |
|---|---|---|
| Enter / Space | Trigger | ポップオーバーを開きます(fandhe-frontend-wasm-full の headless part → action 対応表が "toggle" を dispatch)。 |
| Enter / Space | CloseTrigger | ポップオーバーを閉じます(同対応表が "close" を dispatch)。 |
| Escape | — | 最上位のポップオーバーを閉じます。data-close-on-escape="false" で無効化できます。 |
| Tab / Shift+Tab | — | フォーカストラップはありません(通常の文書順でフォーカスが移動します)。参考サイト(ark-ui/Radix)の「Esc 後に trigger へフォーカスを復帰する」挙動は未実装です。 |
参考サイトとの差分
ark-ui・Radix Primitives・chakra-ui と突合し、content の tabindex="-1" 固定付与を追加しました。anatomy(11 パート)・data-* 語彙の増減はありません。一方、以下は意図的に合わせていません。
- Radix
Portal: DOM 配置の関心のため不採用です。 - zag の
data-placement:data-side/data-align(positionerへ付与)が同役割を担うため置き換えていません。 - zag の
data-expanded(content):data-state+aria-expandedと重複するため不採用です。 - zag の trigger
data-ownedby/data-value/data-current(複数トリガー識別):aria-controlsによる id 関連付けが同等の役割を担うため不採用です(dialogと同判断)。 - chakra-ui の Header / Body / Footer:
fandhe-frontend-pre-styled-ui(Themes 層)の関心のため headless anatomy には持ち込みません。 - close-trigger の既定
aria-label: アイコンボタン等の用途を想定し、内容を強制しない既存方針のため呼び出し側の責務のまま維持しています。 - フォーカストラップ・開時の autoFocus・閉鎖時の trigger へのフォーカス復帰: 参考サイトは Esc 後に trigger へフォーカスを復帰させますが、本リポジトリでは未実装です(
focus_trap::should_trapは dialog scope のみを対象とします)。
スタイル済みの表示例は Popover を参照してください。
関連 API: fandhe-frontend-headless-ui API
自前 CSS の最小例
Themes 版を使わず本部品を直接使う場合、[data-scope="popover"][data-part="..."] セレクタでスタイルを当てます。author スタイルの display が UA の [hidden] { display: none } を上書きして closed 状態が見えてしまわないよう、positioner/content には [hidden] ガードを必ず含めます。
[data-scope="popover"][data-part="root"] {
position: relative;
display: inline-block;
}
[data-scope="popover"][data-part="positioner"] {
position: absolute;
top: 100%;
left: 0;
}
[data-scope="popover"][data-part="positioner"][hidden],
[data-scope="popover"][data-part="content"][hidden] {
display: none;
}
[data-scope="popover"][data-part="content"] {
background: #fff;
border: 1px solid rgb(0 0 0 / 0.1);
border-radius: 8px;
padding: 1rem;
box-shadow: 0 0.25rem 1rem rgb(0 0 0 / 0.15);
}
[data-scope="popover"][data-part="arrow"] {
position: absolute;
width: 0.5rem;
height: 0.5rem;
}Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Details
More information here.
▾Details
More information here.
▾Features
- Root / Trigger / Anchor / Positioner / Arrow / ArrowTip / Content / Title / Description / CloseTrigger / Indicator の 11 anatomy パーツと、Disclosure を埋め込んだ開閉状態機械 Popover を提供する。
- trigger は type="button" を固定付与し、aria-haspopup="dialog"・aria-expanded・(controls が Some のとき)aria-controls を持つ。
- content は role="dialog" を固定付与し、labelledby/describedby が Some のときのみ title/description と対で関連付ける。content は tabindex="-1" を固定付与する(zag popover.connect.ts と同じく、プログラム的フォーカスのみを許可する前提。イシュー #1642)。
- trigger/close-trigger の click → dispatch 配線("toggle"/"close")、Escape・外側クリックでの閉鎖は fandhe-frontend-wasm-full(headless の part → action 対応表・overlay モジュール)が実 DOM 配線を担う。content の attrs 経由で data-close-on-escape="false" / data-close-on-interact-outside="false"("false" リテラルのときのみ無効化)を渡せる。フォーカストラップ・開時の autoFocus・閉鎖時の trigger へのフォーカス復帰は未実装である(focus_trap::should_trap は data-scope="dialog" のみを対象とし popover を含まない、イシュー #1642 で判明)。
Anatomy
root
trigger
anchor
positioner
content
arrow
arrow-tip
title
description
close-trigger
indicatorAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root: state | OpenState | Closed | 開閉状態(data-state へ反映)。 |
trigger: state | OpenState | Closed | aria-expanded/data-state へ反映される開閉状態。 |
trigger: disabled | bool | — | ネイティブ disabled 存在属性と data-disabled の両方へ反映する disabled 状態。 |
trigger: controls | Option<&str> | — | Some のとき aria-controls で content と関連付ける。 |
positioner: state | OpenState | Closed | closed のとき hidden 存在属性を付与する配置ラッパーの開閉状態。 |
content: state | OpenState | Closed | 開閉状態(closed のとき hidden 存在属性を付与)。 |
content: id | Option<&str> | — | trigger の controls と対で aria-controls 関連付けを成立させる。 |
content: labelledby | Option<&str> | — | Some のとき title の id と対で aria-labelledby 関連付けを成立させる。 |
content: describedby | Option<&str> | — | Some のとき description の id と対で aria-describedby 関連付けを成立させる。 |
title: id | Option<&str> | — | content の labelledby と対にする。 |
description: id | Option<&str> | — | content の describedby と対にする。 |
indicator: state | OpenState | Closed | 開閉状態のみを data-state へ反映する最小主義な装飾用パーツ。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
content | data-state | closed, open |
indicator | data-state | closed, open |
positioner | data-state | closed, open |
root | data-state | closed, open |
trigger | data-disabled | (値なし) |
trigger | data-state | closed, open |
Examples
Minimal content
title/description を持たず close_trigger のみを含む、最小構成の Popover content の例です。
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Enter / Space (trigger) | ネイティブ button 要素の click 相当が成立し、fandhe-frontend-wasm-full の headless part → action 対応表が "toggle" を dispatch する。 |
| Enter / Space (close-trigger) | 同対応表が "close" を dispatch する。 |
| Escape | overlay::close_on_escape_for が最上位オーバーレイに "close" を通知する(push_overlay の登録と実際の dispatch は #580 統合層の責務)。data-close-on-escape="false" で無効化できる。 |
| Tab / Shift+Tab | フォーカストラップは無い(focus_trap::should_trap は data-scope="dialog" のみを対象とし popover は含まない)。通常の文書順でフォーカスが移動する。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-haspopup="dialog" | trigger に固定付与。 |
| aria-expanded | trigger に付与。開閉状態を反映する。 |
| aria-controls | trigger に付与。controls が Some のとき content と関連付ける。 |
| role="dialog" | content に固定付与。 |
| aria-labelledby / aria-describedby | content に付与。labelledby/describedby が Some のときのみ出力される。 |
| tabindex="-1" | content に固定付与。プログラム的フォーカスのみを許可する(イシュー #1642)。 |