Tooltip
吹き出しヒントです。fandhe-frontend-headless-ui の tooltip mod は Root / Trigger / Positioner / Content / Arrow / ArrowTip の 6 anatomy パーツを提供します。WAI-ARIA tooltip パターンに従い、trigger は aria-describedby で content(role="tooltip")と関連付けます。aria-expanded/aria-controls は使用しません(Collapsible 等の disclosure 系との違い)。headless-ui 自体はタイマー・キー・ポインタを解釈しません。openDelay/closeDelay/interactive は fandhe-frontend-wasm-full の tooltip::wiring::TooltipDelayController(data-open-delay/data-close-delay/data-interactive 属性で設定)、Escape 閉鎖は同 overlay が実装済みです。
キーボード操作
| キー | 対象 | 効果 |
|---|---|---|
| Tab | Trigger | trigger はネイティブ button 要素のため、ブラウザ標準でフォーカス到達します(disabled 時は除外)。fandhe-frontend-wasm-full の tooltip::wiring::TooltipDelayController::register_tooltip が focusin で遅延なしに open を、focusout で close を要求します(ark-ui / Radix の「Tab で開閉」と同義)。 |
| Escape | — | overlay::OverlayKind::Tooltip は close_on_escape が既定 true です(data-close-on-escape="false" で無効化可能)。 |
| Enter / Space | Trigger | ネイティブ button の click が発火し、headless::MAPPING_TABLE が "toggle" を dispatch します。参照(ark closeOnClick: true / Radix の Space・Enter)は「閉じるのみ」であり、本実装の toggle(開閉反転)との差は fandhe-frontend-wasm-full 側の挙動差です(下記スコープ外候補)。 |
参考サイトとの差分
ark-ui・chakra-ui・Radix Primitives と突合した結果、是正すべき具体的な欠落は見つかりませんでした(イシュー #1645)。anatomy(6 パート、Radix の Provider > Root > Trigger > Portal > Content > Arrow を含む)・data-state/data-disabled 語彙・role="tooltip"/aria-describedby はいずれも一致しています。一方、以下は意図的に合わせていません。
- Zag/chakra の
data-expanded:data-stateと重複するため不採用です。 - Zag/chakra の
data-placement、Radix の[data-side]/[data-align]:positionerのdata-side/data-align(positioning、#590)が同役割を担うため置き換えていません。 - Radix の
[data-state]語彙delayed-open/instant-open: 本実装はOpenState("open"/"closed")語彙統一を優先しています。 aria-describedbyの常時出力: zag/Radix は open 時のみ出力しますが、本実装はdescribedbyがSomeのとき状態に関係なく常時出力します(SSR 静的出力の性質上。hiddenな参照先も accessible description の算出に含まれるため害はなく、むしろ SSR/no-JS で説明が結び付く利点があります)。Provider/Portal: 遅延設定共有・DOM 配置の関心のため headless anatomy には持ち込みません。
上記の差分に伴う data-*・パートの増減は無いため、Themes 側イシュー #1548(closed)への追加コメントは行っていません。
スコープ外候補(是正対象ではなく、別途起票を検討する余地がある事項):
fandhe-frontend-wasm-fullの tooltip trigger click →"toggle"(headless::MAPPING_TABLE)を参照準拠の「閉じるのみ」(arkcloseOnClick/ Radix Space・Enter)へ寄せるかの検討crates/headless-ui/src/tooltip.rsrustdoc(モジュール doc §スコープ外・contentの doc)の「openDelay/closeDelay/interactive/closeOnEscape はスコープ外」記述の陳腐化是正(現在はfandhe-frontend-wasm-full側に実装済みのため。src/変更のため semver バンプまたはversion-bump-exempt宣言を伴う別 PR)aria-describedbyを open 時のみ出力する参照挙動への追随要否(fandhe-frontend-wasm-full側での動的付け外しを含む設計判断)
スタイル済みの表示例は Tooltip を参照してください。
関連 API: fandhe-frontend-headless-ui API
自前 CSS の最小例
Themes 版を使わず本部品を直接使う場合、[data-scope="tooltip"][data-part="..."] セレクタでスタイルを当てます。author スタイルの display が UA の [hidden] { display: none } を上書きして closed 状態が見えてしまわないよう、positioner/content には [hidden] ガードを必ず含めます。
[data-scope="tooltip"][data-part="root"] {
position: relative;
display: inline-block;
}
[data-scope="tooltip"][data-part="positioner"] {
position: absolute;
top: 100%;
left: 0;
}
[data-scope="tooltip"][data-part="positioner"][hidden],
[data-scope="tooltip"][data-part="content"][hidden] {
display: none;
}
[data-scope="tooltip"][data-part="content"] {
background: #1a1a1a;
color: #fff;
border-radius: 4px;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
}
[data-scope="tooltip"][data-part="trigger"][data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
[data-scope="tooltip"][data-part="arrow"] {
position: absolute;
width: 0.5rem;
height: 0.5rem;
}Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- WAI-ARIA tooltip パターンに従い、trigger は aria-describedby で content(role="tooltip")と関連付ける。aria-expanded/aria-controls は使用しない(trigger 自体が展開可能なウィジェットではないため)。
- Root / Trigger / Positioner / Content / Arrow / ArrowTip の 6 anatomy パーツと、Disclosure を埋め込んだ開閉状態機械 Tooltip を提供する。
- headless-ui 自体はタイマー・キー・ポインタを解釈しない。openDelay/closeDelay/interactive は fandhe-frontend-wasm-full の tooltip::wiring::TooltipDelayController(data-open-delay/data-close-delay/data-interactive 属性で設定)、Escape 閉鎖は同 overlay が実装済み。
- ark-ui / chakra-ui / Radix Primitives と突合し、anatomy 6 パーツ・data-state/data-disabled 語彙・role="tooltip"/aria-describedby は一致。data-expanded/data-placement/Radix の delayed-open・instant-open は意図的差分として非採用(イシュー #1645、是正なし)。
Anatomy
root
trigger
positioner
content
arrow
arrow-tipAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root: state | OpenState | Closed | 開閉状態(data-state へ反映)。 |
trigger: state | OpenState | Closed | data-state へ反映される開閉状態。 |
trigger: disabled | bool | — | ネイティブ disabled 存在属性と data-disabled の両方へ反映する disabled 状態。 |
trigger: describedby | Option<&str> | — | Some のとき aria-describedby で content と関連付ける(WAI-ARIA tooltip パターン)。 |
positioner: state | OpenState | Closed | closed のとき hidden 存在属性を付与する配置ラッパーの開閉状態。 |
content: state | OpenState | Closed | 開閉状態(closed のとき hidden 存在属性を付与)。 |
content: id | Option<&str> | — | trigger の describedby と対で aria-describedby 関連付けを成立させる。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
content | data-state | closed, open |
positioner | data-state | closed, open |
root | data-state | closed, open |
trigger | data-disabled | (値なし) |
trigger | data-state | closed, open |
Examples
Disabled trigger
disabled な trigger はネイティブ disabled 属性と data-disabled が付与され、フォーカス・展開ができなくなります。
Custom CSS
data-scope / data-part / data-state / data-disabled セレクタで自前 CSS を当てる最小例です。
利用者が data-scope / data-part / data-state / data-disabled セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。
[data-scope="tooltip"][data-part="root"] {
position: relative;
display: inline-block;
}
[data-scope="tooltip"][data-part="positioner"] {
position: absolute;
top: 100%;
left: 0;
}
[data-scope="tooltip"][data-part="positioner"][hidden],
[data-scope="tooltip"][data-part="content"][hidden] {
display: none;
}
[data-scope="tooltip"][data-part="content"] {
background: #1a1a1a;
color: #fff;
border-radius: 4px;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
}
[data-scope="tooltip"][data-part="trigger"][data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
[data-scope="tooltip"][data-part="arrow"] {
position: absolute;
width: 0.5rem;
height: 0.5rem;
}
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Tab | trigger はネイティブ button のためフォーカス到達する(disabled 時は除外)。fandhe-frontend-wasm-full の tooltip::wiring::TooltipDelayController::register_tooltip が focusin で遅延なしに "open"、focusout で "close" を要求する(ark-ui / Radix の「Tab で開閉」と同義)。 |
| Escape | overlay::OverlayKind::Tooltip は close_on_escape が true(OverlayCloseController が "close" を通知)。data-close-on-escape="false" で無効化可能。 |
| Enter / Space | ネイティブ button の click が発火し headless::MAPPING_TABLE が "toggle" を dispatch する。参照(ark closeOnClick: true / Radix の Space・Enter)は「閉じるのみ」であり、toggle との差は wasm-full 側の挙動差(本イシュー対象外、スコープ外候補)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-describedby | trigger に付与。describedby が Some のとき content と関連付ける。zag/Radix は open 時のみ出力するが、SSR 静的出力では Some なら常時出力する(意図的差分)。 |
| role="tooltip" | content に固定付与。 |
| aria-expanded / aria-controls(非付与) | trigger 自体が展開可能なウィジェットではないため付与しない(Collapsible との違い)。 |
| data-expanded / data-placement(非付与) | zag/Radix 由来だが data-state・positioner の data-side/data-align と重複するため意図的に非採用(イシュー #1645)。 |
| aria-hidden="true" | arrow/arrow_tip に固定付与(装飾用のみ、スクリーンリーダーの読み上げ対象外)。 |