Components
Back to catalog
Component detail entry
Overlay
@vean/ui
SHoverCard

HoverCard

HoverCard belongs to the Overlay category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Hover Card

Overview

Displays a richer preview card when the trigger is hovered or receives focus. SHoverCard combines the Aria HoverCardRoot/HoverCardTrigger/HoverCardPositioner/HoverCardPopup/HoverCardArrow primitive family (built on the shared Popper) with the hoverCardVariants style recipe (3 slots, 6 sizes).

Use a hover card for a non-blocking, hover-triggered preview (user profiles, repository previews, inline metadata). For a small text hint use tooltip; for click-triggered rich content use popover.

Usage

Features

  • 🧩 Aria/styled split — HoverCardCompact aggregates the popper trigger, positioner, popup and arrow; SHoverCard only injects styles and forwards slots/events
  • ⏱️ Open/close delay — openDelay (default 700ms) / closeDelay (default 300ms) tune the hover latency
  • 🎯 Placement — full popper placement control with collision avoidance and side-aware slide animations
  • 🔽 Arrow — showArrow renders a positioned arrow; configurable via arrowProps
  • ⌨️ Focus trigger — also opens on keyboard focus, not just pointer hover
  • 📐 6 sizes — xs–2xl size; per-slot ui overrides
  • ♿ Accessible — dismiss on Escape/outside interaction, axe-core zero violations open and closed

Component family

  • SHoverCard (styled) — the entry wrapper; hoverCardVariants recipe with dynamic slot forwarding
  • HoverCardRoot (Aria) — the state owner; open via useControllableState, openDelay/closeDelay, provides the popper root
  • HoverCardTrigger (Aria) — the anchor that opens the card on hover/focus
  • HoverCardPositioner / HoverCardPositionerImpl (Aria) — the dismissable, positioned surface (built on PopperPositioner)
  • HoverCardPopup (Aria) — the popup body
  • HoverCardArrow (Aria) — the popper arrow
  • HoverCardCompact (Aria) — the aggregated composite; composes trigger/positioner/popup/arrow and exposes the slots

Demo

Basic

Custom Styling

API

Aria Layer

8

HoverCard

17 Props4 Emits2 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
class of popup
size
ThemeSize
—
Visual size of the component.
ui
Partial<HoverCardUi>
—
Per-slot class overrides for the component.
placement
import("@/index").Placement
—
Placement.
showArrow
boolean
—
Whether to show an arrow.
triggerProps
PopperAnchorProps
—
Properties forwarded to the trigger element.
portalProps
HoverCardPortalProps
—
Properties forwarded to the portal element.
positionerProps
HoverCardPositionerProps
—
Properties forwarded to the positioner element.
popupProps
HoverCardPopupProps
—
Properties forwarded to the popup element.
arrowProps
HoverCardArrowProps
—
Properties forwarded to the arrow element.
defaultOpen
boolean
—
The open state of the hover card when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the hover card.
openDelay
number
—
The duration from when the pointer enters the trigger until the hover card opens.
closeDelay
number
—
The duration from when the pointer leaves the trigger or popup until the hover card closes.
dir
Direction
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean, reason?: PopperOpenChangeReason | undefined
Event handler called when the open state of the hover card changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
Slots
Slot NameParametersDescription
default
—
Custom content for the default slot.
trigger
—
Custom content for the trigger slot.

HoverCardArrow

HoverCardCompact

14 Props4 Emits2 Slots
Props
PropTypeDefaultDescription
placement
import("@/index").Placement
—
Placement.
showArrow
boolean
—
Whether to show an arrow.
triggerProps
PopperAnchorProps
—
Properties forwarded to the trigger element.
portalProps
HoverCardPortalProps
—
Properties forwarded to the portal element.
positionerProps
HoverCardPositionerProps
—
Properties forwarded to the positioner element.
popupProps
HoverCardPopupProps
—
Properties forwarded to the popup element.
arrowProps
HoverCardArrowProps
—
Properties forwarded to the arrow element.
defaultOpen
boolean
—
The open state of the hover card when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the hover card.
openDelay
number
—
The duration from when the pointer enters the trigger until the hover card opens.
closeDelay
number
—
The duration from when the pointer leaves the trigger or popup until the hover card closes.
dir
Direction
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean, reason?: PopperOpenChangeReason | undefined
Event handler called when the open state of the hover card changes.
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.
Slots
Slot NameParametersDescription
default
—
Custom content for the default slot.
trigger
—
Custom content for the trigger slot.

HoverCardPopup

HoverCardPortal

HoverCardPositioner

23 Props3 Emits
Props
PropTypeDefaultDescription
placement
Placement
undefined
The placement of the floating element. If used, it will override the `side` and `align` props.
side
Side
'bottom'
The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.
sideOffset
number
0
The distance in pixels from the trigger.
sideFlip
boolean
true
Flip to the opposite side when colliding with boundary.
align
Align
'center'
The preferred alignment against the trigger. May change when collisions occur.
alignOffset
number
0
An offset in pixels from the `start` or `end` alignment options.
alignFlip
boolean
true
Flip alignment when colliding with boundary. May only occur when `prioritizePosition` is true.
avoidCollisions
boolean
true
When `true`, overrides the side and align preferences to prevent collisions with boundary edges.
collisionBoundary
Element | (Element | null)[] | null
[ ]
The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.
collisionPadding
Padding
0
The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.
arrowPadding
number
0
The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners.
hideShiftedArrow
boolean
true
When `true`, hides the arrow when it cannot be centered to the reference element.
sticky
'partial' | 'always'
'partial'
The sticky behavior on the align axis. `partial` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst "always" will keep the content in the boundary regardless.
hideWhenDetached
boolean
false
Whether to hide the content when the trigger becomes fully occluded.
positionStrategy
'fixed' | 'absolute'
'fixed'
The type of CSS position property to use.
updatePositionStrategy
'always' | 'optimized'
'optimized'
Strategy to update the position of the floating element on every animation frame.
disableUpdateOnLayoutShift
boolean
false
Whether to disable the update position for the content when the layout shifted.
prioritizePosition
boolean
false
Force content to be position within the viewport. Might overlap the reference element, which may not be desired.
reference
ReferenceElement
—
The custom element or virtual element that will be set as the reference to position the floating element. If provided, it will replace the default anchor element.
trapFocus
boolean
modal
Whether focus is trapped inside the popup while open (Tab cycles within the layer and body scroll is locked for modal layers).
disableHoverableContent
boolean
false
When `true`, hovering the popup closes instead of keeping it open (the grace area is disabled, so leaving the trigger closes the layer immediately).
onGracePointerExit
(() => void)
—
Callback invoked when the pointer finally leaves the grace area. Lets an upper layer (e.g. Tooltip) run area-scoped close logic without registering its own second grace area.
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.
Emits
Emit NameParametersDescription
escapeKeyDown
KeyboardEvent
Event handler called when the escape key is down. Can be prevented.
pointerDownOutside
PointerDownOutsideEvent
Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented.
focusOutside
FocusOutsideEvent
Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented.

HoverCardRoot

7 Props1 Emits
Props
PropTypeDefaultDescription
defaultOpen
boolean
—
The open state of the hover card when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the hover card.
openDelay
number
—
The duration from when the pointer enters the trigger until the hover card opens.
closeDelay
number
—
The duration from when the pointer leaves the trigger or popup until the hover card closes.
dir
Direction
—
—
modal
boolean
—
—
disabled
boolean
—
—
Emits
Emit NameParametersDescription
update:open
boolean, reason?: PopperOpenChangeReason | undefined
Event handler called when the open state of the hover card changes.

HoverCardTrigger

Notes

Architecture and benchmark differences

HoverCardCompact owns the trigger/positioner/popup/arrow composition while every primitive stays style-free and only the UI wrapper injects the hoverCardVariants classes. This mirrors radix-ui/shadcn-ui’s headless split, built on the shared Popper primitives. Ant Design, Element Plus, Mantine and Naive UI ship a single styled popover used for hover previews; VeanUI exposes a dedicated hover-card with configurable openDelay/closeDelay, per-slot *Props, an arrow toggle and a size scale the single-package libraries generally omit.

CapabilityVeanUIshadcn/uiAnt DesignElement PlusMantineNaive UI
Aria/styled split✅✅————
Open/close delay✅✅——✅—
Popper placement (12)✅✅✅✅✅✅
Arrow✅✅————
Sizes (6)✅—————
Focus trigger✅✅✅✅✅✅

— = unsupported or a different interaction model (hover previews fold into the generic popover).

Cautions

  • The card opens on hover and keyboard focus; tune openDelay/closeDelay to reduce accidental triggers (defaults 700ms/300ms).
  • The popup is rendered through a Portal (teleported to document.body); position it inside a relatively-positioned ancestor only with portalProps: { disabled: true }.
  • showArrow renders an arrow; arrowProps can override its position/classes.
  • The hover card is non-modal and dismisses on Escape or outside interaction; it does not trap focus.

Roadmap

N/A — hover-card is feature-complete for the current parity set.

FAQ

How do I adjust the open/close timing?

Set open-delay and close-delay (ms):

<SHoverCard :open-delay="200" :close-delay="100">
  <template #trigger><SButton>Hover me</SButton></template>
  <div>Preview content</div>
</SHoverCard>

How do I position the card?

Use placement:

<SHoverCard placement="top">
  <template #trigger><SButton>Hover me</SButton></template>
  <div>Preview content</div>
</SHoverCard>

How do I hide the arrow?

Set show-arrow={false}:

<SHoverCard :show-arrow="false">
  <template #trigger><SButton>Hover me</SButton></template>
  <div>Preview content</div>
</SHoverCard>

How do I control the open state?

Bind open with v-model or use defaultOpen:

<SHoverCard v-model:open="open">
  <template #trigger><SButton>Hover me</SButton></template>
  <div>Preview content</div>
</SHoverCard>

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.20.0

2026-05-12

Compare release

Optimization

simplify HoverCard component by using HoverCardCompact

Scope: hover-cardAuthors: soybeanjsView commitf23ad

Optimization

rename forwardedRootProps to forwardedProps for consistency

Scope: hover-cardAuthors: soybeanjsView commitd2545

Optimization

simplify slot handling and remove unused variables

Scope: hover-cardAuthors: soybeanjsView commit4d747

v0.17.0

2026-05-03

Compare release

Fix

add sub-area attribute for hover card positioning

Scope: hover-cardAuthors: soybeanjsView commit130a3

v0.16.0

2026-05-01

Compare release

Feature

implement Compact components for Card, Popover, Editable, HoverCard, NavigationMenu, Pagination and Stepper

Scope: componentsAuthors: soybeanjsView commit6cbdc

Optimization

add prioritizePosition prop to HoverCardPositioner

Scope: hover-cardAuthors: soybeanfeView commite53db