Vize

Hover Card

Accessible, unstyled hover card for previewing linked content on hover or focus.

Package @vizejs/ui/hover-card
Maturity stable
Own the source vize lib pull hover-card
Requires context, controllable-state, dismissable-layer, hover, id, pointer-grace, portal, positioner, presence, primitive
Aliases hover card, preview card, link preview, profile card
Covers Radix UI HoverCard, Reka UI HoverCard, Ark UI HoverCard

Usage

import { HoverCard, HoverCardRoot, HoverCardContent, HoverCardTrigger, HoverCardArrow } from "@vizejs/ui/hover-card";

Or copy the source into your project with vize lib pull hover-card (see Source Distribution).

API

HoverCard

Source: src/families/overlays/hover-card/hover-card-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned HoverCard base id. null and undefined select a deterministic fallback.
open boolean undefined Controlled open state. undefined selects uncontrolled behavior.
defaultOpen boolean false Initial open state for uncontrolled use.
disabled boolean false Disable pointer, focus, and touch opening and close an open card.
openDelay number 700 Milliseconds the pointer or focus must rest on the trigger before opening.
closeDelay number 300 Milliseconds after the pointer or focus leaves before closing. Moving into the card or through the pointer-grace corridor cancels the close.
touchBehavior HoverCardTouchBehavior "ignore" Touch handling on the trigger. Hover cards are supplementary, so touch is ignored by default and taps keep native link behavior.
longPressDelay number 500 Milliseconds a touch must be held when touchBehavior is "long-press".

Events

Event Payload Description
update:open [value: boolean] Fired when the HoverCard requests a controlled open value.
open-change [value: boolean, previous: boolean, nativeEvent: Event | null] Fired after any distinct open-state request.

Slots

Slot Slot props Description
default HoverCardSlotState Compound HoverCard children. Receives the current open state.

Exposed

Member Type Description
cancelPending —
closeDelay —
contentId —
disabled —
id —
open —
openDelay —
reason —
scheduleClose —
scheduleOpen —
setOpen —
state —
triggerId —

HoverCardRoot

Source: src/families/overlays/hover-card/hover-card-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned HoverCard base id. null and undefined select a deterministic fallback.
open boolean undefined Controlled open state. undefined selects uncontrolled behavior.
defaultOpen boolean false Initial open state for uncontrolled use.
disabled boolean false Disable pointer, focus, and touch opening and close an open card.
openDelay number 700 Milliseconds the pointer or focus must rest on the trigger before opening.
closeDelay number 300 Milliseconds after the pointer or focus leaves before closing. Moving into the card or through the pointer-grace corridor cancels the close.
touchBehavior HoverCardTouchBehavior "ignore" Touch handling on the trigger. Hover cards are supplementary, so touch is ignored by default and taps keep native link behavior.
longPressDelay number 500 Milliseconds a touch must be held when touchBehavior is "long-press".

Events

Event Payload Description
update:open [value: boolean] Fired when the HoverCard requests a controlled open value.
open-change [value: boolean, previous: boolean, nativeEvent: Event | null] Fired after any distinct open-state request.

Slots

Slot Slot props Description
default HoverCardSlotState Compound HoverCard children. Receives the current open state.

Exposed

Member Type Description
open boolean Whether the card content is visible.
disabled boolean Whether pointer, focus, and touch opening are disabled.
state HoverCardState Stable state token for styling and tests.
reason HoverCardOpenReason | null Why the card last opened, or null while closed.
id string Root-owned base id.
triggerId string Id wired to the trigger.
contentId string Id wired to the content.
openDelay number Milliseconds before pointer or focus intent opens the card.
closeDelay number Milliseconds before pointer or focus departure closes the card.
setOpen (value: boolean, event?: Event | null) => boolean Request a specific open value immediately and report whether it differs.
scheduleOpen (event?: Event | null) => boolean Open after openDelay, cancelling a pending close.
scheduleClose (event?: Event | null) => boolean Close after closeDelay, cancelling a pending open.
cancelPending () => boolean Cancel any pending delayed open or close. Returns whether a timer was cleared.

HoverCardContent

Source: src/families/overlays/hover-card/hover-card-content.vue

Props

Prop Type Default Description
forceMount boolean false Keep the card mounted while closed.
to string | HTMLElement "body" CSS selector or element the card layer is moved into.
portalDisabled boolean false Render in place instead of teleporting.
defer boolean true Keep content in place until the target exists, avoiding SSR mismatch.
placement Placement "bottom" Preferred placement before collision handling.
strategy PositionerStrategy "fixed" CSS positioning mode published on the floating host.
offset number 8 Gap on the main axis between trigger and card.
collisionPadding number 8 Viewport padding the card should not cross.
flip boolean true Flip to the opposite side when the preferred side overflows more.
shift boolean true Shift the card back into the viewport after flip.
hide boolean true Hide when the trigger no longer intersects the viewport.
updateOnScroll boolean true Recalculate while ancestors scroll.
updateOnResize boolean true Recalculate when the document or visual viewport resizes.
viewport Rect undefined Viewport used for flip, shift, and hide.
closeOnEscape boolean true Let Escape close the card.
closeOnPointerDownOutside boolean true Let an outside pointer-down close the card.
ariaLabel string undefined Accessible name for the card when its contents do not provide one.

Events

Event Payload Description
escape-key-down [event: DismissableLayerEscapeKeyDownEvent] Fired before Escape requests dismissal.
pointer-down-outside [event: DismissableLayerPointerDownOutsideEvent] Fired before an outside pointer-down requests dismissal.
dismiss [event: DismissableLayerDismissEvent] Fired after an unprevented dismissal request.

Slots

Slot Slot props Description
default HoverCardContentSlotState Card contents. Receives open state, open reason, and preferred placement.

Exposed

Member Type Description
open boolean Whether the card content is visible.
disabled boolean Whether pointer, focus, and touch opening are disabled.
state HoverCardState Stable state token for styling and tests.
reason HoverCardOpenReason | null Why the card last opened, or null while closed.
element HTMLDivElement | null Rendered card element.

HoverCardTrigger

Source: src/families/overlays/hover-card/hover-card-trigger.vue

Props

Prop Type Default Description
as PrimitiveAs "a" Element or component rendered as the trigger. Hover cards usually enhance a link, so the default is a native anchor; pass href and other link attributes as fallthrough attributes.
disabled boolean false Ignore pointer, focus, and touch intent from this trigger.

Slots

Slot Slot props Description
default HoverCardSlotState Trigger contents. Receives the current HoverCard state.

Exposed

Member Type Description
element HTMLElement | null Rendered trigger element.
focus (options?: FocusOptions) => void Move focus to the trigger.

HoverCardArrow

Source: src/families/overlays/positioner/positioner-arrow.vue

Slots

Slot Slot props Description
default { readonly x: number | null; readonly y: number | null } Decorative arrow contents. Receives coordinates for optional custom drawing.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
x —
y —

Behavior

Normative behavior for the @vizejs/ui/hover-card compound primitive. A hover card previews supplementary content for sighted pointer and keyboard users; the trigger keeps its native link semantics and the card is never the only way to reach its content. Every row is proven by the named mounted-DOM, SSR, or compile-time test.

State x input Observable outcome Proven by
closed, mouse or pen pointerenter on the trigger The card opens after openDelay (default 700 ms), never earlier; the trigger gains aria-describedby and content gets data-reason="hover". hover opens after openDelay with link semantics and describedby wiring
open, pointerleave from the trigger The card closes after closeDelay (default 300 ms); re-entering the trigger first cancels the close. leaving closes after closeDelay unless the pointer returns or enters the card
open, pointer enters or leaves the card Entering the card cancels a pending close; leaving the card schedules one. leaving closes after closeDelay unless the pointer returns or enters the card
open, pointer travels from the trigger toward the card Pointer moves inside the pointer-grace safe triangle cancel the close; moves outside schedule it again. pointer grace keeps the card open while travelling toward it
closed, trigger focus The card opens after openDelay with data-reason="focus". focus opens the card and blur closes it unless focus moves into the card
open, trigger blur Focus moving into the card keeps it open; focus moving elsewhere schedules the close. focus opens the card and blur closes it unless focus moves into the card
open, Escape on the trigger or card; outside pointer-down The card closes immediately through the dismissable layer; Escape is consumed and dismiss reports the reason. Escape and outside pointer-down dismiss immediately
touchBehavior="ignore", touch input Touch never opens the card and taps keep native link activation. touch is ignored by default and keeps native link activation
touchBehavior="long-press", touch held Holding for longPressDelay opens the card (data-reason="long-press"), suppresses the context menu and the one follow-up click; moving past the touch slop cancels. long-press touch opens the card and suppresses the follow-up click
disabled root Pointer, focus, and touch intent are ignored and an open card closes. disabled roots ignore intent and close an open card
controlled open Intent emits update:open and open-change while rendered state follows the prop. controlled open follows the parent after emitting requests
root expose scheduleOpen, scheduleClose, cancelPending, setOpen, normalized delays, ids, reason, and state are available. root exposes delays and programmatic scheduling
parts outside the root Mounting throws VIZE_UI_CONTEXT_MISSING. trigger and content require a HoverCard root
SSR, closed Isolated requests render byte-identical span-only markup that is valid inside <p>, with no document listeners or timers. renders byte-identical closed hover-card markup that nests in phrasing content
SSR, defaultOpen Content renders in place through the deferred portal and hydrates without warnings before teleporting. renders default-open content in place and hydrates without diagnostics
public types Touch behavior, open reason, delays, and placement are closed, typed contracts. src/families/overlays/hover-card/hover-card.types.test-d.ts
DOM/SSR/Vapor Root, trigger, and content compile in every renderer lane. scripts/check-renderers.ts

Components

Component State x input Outcome
hover-card-root.vue controlled or uncontrolled open, timers Owns open state, open/close delays, open reason, and emits update:open/open-change.
hover-card-trigger.vue hover, focus, blur, Escape, touch Schedules opening and closing, tracks the pointer-grace corridor, and handles long-press touch.
hover-card-content.vue open, pointer enter/leave, focus, dismiss Portals and positions the card, keeps it open while hovered or focused, and dismisses via Escape or outside pointer-down.

Public Root Props

Prop Type Default Contract
id string | null undefined Consumer-owned base id.
open boolean undefined Controlled open state.
defaultOpen boolean false Initial uncontrolled open state.
disabled boolean false Ignore intent and close an open card.
openDelay number 700 Milliseconds before hover or focus opens. Invalid values mean 0.
closeDelay number 300 Milliseconds before departure closes. Invalid values mean 0.
touchBehavior "ignore" | "long-press" "ignore" Touch policy.
longPressDelay number 500 Touch hold duration for "long-press".

Parts And Data

Target Public contract
Root <span>, part="root", data-vize-ui="hover-card-root", data-state, data-disabled
Trigger <a> by default (as), part="trigger", data-vize-ui="hover-card-trigger", data-state, data-disabled
Content host <span>, part="content-host", data-vize-ui="hover-card-content-host"
Content part="content", data-vize-ui="hover-card-content", data-state, data-placement, data-reason, data-top-layer
Arrow HoverCardArrow is the shared PositionerArrow and must render inside HoverCardContent.

HoverCard ships no stylesheet. Consumers own all visual styling.