Skip to content
fandhe-frontendcore v0.4.3
GitHub

Hover Card

リンク先プレビュー等、hover / focus で開閉するオーバーレイです。fandhe-frontend-headless-ui の hover_card mod は Root / Trigger / Positioner / Content / Arrow / ArrowTip の 6 anatomy パーツを提供します。trigger はリンク先プレビュー用途の a 要素であり、HoverCardDelays(open_ms/close_ms、ark-ui 既定の 600/300 ms)を data-open-delay/ data-close-delay として決定的に出力します。WAI-ARIA に hover card 専用パターンは存在しないため、aria-expanded/aria-controls/aria-haspopup 及び固定 role を一切付与しません(Tooltip との違い)。

キーボード操作

キー対象効果
TabTriggertrigger はネイティブ a 要素のため、href を渡している場合はブラウザ標準でフォーカス到達します。Radix の「Tab で hover card を開閉」に相当する focus/blur 駆動の開閉配線は fandhe-frontend-wasm-full 側の責務で未配線です。
EnterTriggerhref を渡している場合、リンク先へ遷移します(ブラウザ標準)。hover card 自体の開閉はこのキー操作では行いません。

参考サイトとの差分

Zag.js(hover-card.connect.ts)・ark-ui・Radix Primitives・Radix Themes・chakra-ui と突合し、是正すべき欠落は見つかりませんでした(イシュー #1641)。anatomy(6 パート)・data-state 語彙(open/closed)・ARIA 非付与方針はいずれも一致しています。一方、以下は意図的に合わせていません。

  • data-side/data-align の付与先: Radix は content へ、Zag は trigger/content の双方へ出しますが、本クレートは positioning(#590)の規約どおり positioner へ透過させます(Tooltip/Popover と同型。hover-card だけ変えると規約が分裂するため)。
  • tabindex="-1"(content)・dir・自動 id(Zag): hover/focus のタイマー・DOM 配線が fandhe-frontend-wasm-full に未実装の段階では固定付与しません。
  • 複数トリガー識別(data-value/data-current/data-ownedby、Zag): 機能拡張でありスコープ外候補です(下記参照)。

上記の差分に伴う data-*・パートの増減は無いため、Themes 側イシュー #1523(closed)への追加コメントは行っていません。

スコープ外候補(是正対象ではなく、別途起票を検討する余地がある事項):

  • 複数トリガー対応(Zag の data-value/data-current/data-ownedby)
  • fandhe-frontend-wasm-full 側の hover/focus タイマー配線・PositionedKind::from_scope("hover-card") への追加
  • 配線後の content tabindex="-1" 付与の再評価

スタイル済みの表示例は Hover Card を参照してください。

関連 API: fandhe-frontend-headless-ui API

自前 CSS の最小例

[data-scope="hover-card"][data-part="..."] セレクタでスタイルを当てます。以下は content の枠・影、closed 時の非表示、trigger のフォーカスリング、positioner の配置調整の最小例です。

CSS
[data-scope="hover-card"][data-part="content"] {
  border: 1px solid #888;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

[data-scope="hover-card"][data-part="content"][data-state="closed"] {
  display: none;
}

[data-scope="hover-card"][data-part="trigger"]:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

[data-scope="hover-card"][data-part="positioner"][data-side="top"] {
  margin-bottom: 8px;
}

Demo

枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。

@example
Example user profile preview.

Features

  • Root / Trigger / Positioner / Content / Arrow / ArrowTip の 6 anatomy パーツと、Disclosure を埋め込んだ開閉状態機械 HoverCard を提供する。trigger はリンク先プレビュー用途の a 要素であり、Tooltip とはこの点が異なる。
  • HoverCardDelays(open_ms 既定 600 / close_ms 既定 300、ark-ui 既定値)を data-open-delay/data-close-delay(10 進の ms 値のみ)として決定的に出力する。実際の hover/focus タイマー駆動は wasm-full 側の責務でスコープ外。
  • WAI-ARIA に hover card 専用パターンが存在しないため、aria-expanded/aria-controls/aria-haspopup 及び content への固定 role を一切付与しない(Tooltip/Popover との違い)。
  • ark-ui の Root > Trigger > Positioner > (Arrow > ArrowTip) + Content の 6 パートと完全一致(イシュー #1641 で Zag.js hover-card.connect.ts・Radix Primitives と突合、是正なし)。data-side/data-align は positioner へ透過させる(tooltip/popover と同型の positioning 規約、#590)。

Anatomy

root
  trigger
  positioner
    content
      arrow
        arrow-tip

API Reference

Arguments

NameTypeDefaultDescription
root: stateOpenStateClosed開閉状態(data-state へ反映)。
root: delaysHoverCardDelaysHoverCardDelays::default()(open_ms: 600, close_ms: 300)data-open-delay/data-close-delay(10 進の ms 値のみ)へ反映される遅延設定。
trigger: stateOpenStateCloseddata-state へ反映される開閉状態。
trigger: hrefOption<&str>—Some のときのみ href 属性を出力する(リンク先プレビュー用途)。
positioner: stateOpenStateClosedclosed のとき hidden 存在属性を付与する配置ラッパーの開閉状態。
content: stateOpenStateClosed開閉状態(closed のとき hidden 存在属性を付与)。
content: idOption<&str>—呼び出し側が任意に使える id(本モジュールは固定の aria-describedby を配線しない)。

Data Attributes

PartAttributeObserved Values
contentdata-stateopen
positionerdata-stateopen
rootdata-close-delay300
rootdata-open-delay600
rootdata-stateopen
triggerdata-stateopen

Examples

Custom delays

open_ms/close_ms を既定値(600/300)から変更し、開くまでの遅延を短く・閉じるまでの遅延を長くした例です。

@team
Opens fast, lingers longer before closing.

Custom CSS

data-scope / data-part / data-state / data-side セレクタで自前 CSS を当てる最小例です。

利用者が data-scope / data-part / data-state / data-side セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。

@example
Custom-styled preview card.
CSS
[data-scope="hover-card"][data-part="content"] {
  border: 1px solid #888;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
[data-scope="hover-card"][data-part="content"][data-state="closed"] {
  display: none;
}
[data-scope="hover-card"][data-part="trigger"]:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}
[data-scope="hover-card"][data-part="positioner"][data-side="top"] {
  margin-bottom: 8px;
}

Accessibility

Keyboard Interactions

KeyDescription
Tabtrigger はネイティブ a 要素(hover_card.rs:150-162)のため、href が Some のときブラウザ標準でフォーカス到達する。Radix の「Tab で hover card を開閉」に相当する focus/blur 配線は fandhe-frontend-wasm-full 側の責務で未配線。
Enterhref が Some の trigger でリンク先へ遷移する(ブラウザ標準)。hover card 自体の開閉はこのキー操作では行わない。

WAI-ARIA

AttributeDescription
aria-expanded / aria-controls / aria-haspopup(非付与)WAI-ARIA に hover card 専用パターンが無いため、trigger には付与しない(Zag.js hover-card.connect.ts・Radix Primitives とも一致、イシュー #1641 突合)。
role(非付与)content にも固定 role を付与しない(Zag.js・Radix とも一致)。Radix の Accessibility 注記: hover card は視覚ユーザー向けであり、content はキーボードユーザーには(フォーカス配線が無い限り)到達不能。
aria-hidden="true"arrow/arrow_tip に固定付与(装飾用のみ、スクリーンリーダーの読み上げ対象外)。