HoverCard
A richer, interactive alternative to Tooltip — opens on hover/focus after a delay and stays open while you move the pointer into the card. Content is fully interactive (links, buttons). Renders with role="dialog".
Features
openDelay, closes after closeDelay.forceMount keeps the card mounted for CSS exit animations.Example
The latest release was shipped by @grace with help from the platform team. Hover the name to preview their profile.
Anatomy
import { HoverCard } from '@wire-ui/react'
<HoverCard.Root>
<HoverCard.Trigger>@wire-ui</HoverCard.Trigger>
<HoverCard.Content side="bottom">
Headless, AI-native component primitives with zero CSS.
</HoverCard.Content>
</HoverCard.Root>Styling
Trigger and Content set data-state ("open" / "closed"); Content also sets data-side. Use these to drive enter/exit transitions and side-specific styling. Content is absolutely positioned relative to the Root (an inline-block wrapper) and given z-index: 50.
<HoverCard.Content className="
opacity-0 transition-opacity
data-[state=open]:opacity-100
data-[side=top]:origin-bottom
data-[side=bottom]:origin-top
">
…
</HoverCard.Content>Using data attributes
/* Animate based on open/closed state */
[data-state="open"] { opacity: 1; }
[data-state="closed"] { opacity: 0; }
/* Side-specific transform origin */
[data-side="top"] { transform-origin: bottom center; }
[data-side="bottom"] { transform-origin: top center; }Root props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Initial open state (uncontrolled) |
onOpenChange | (open: boolean) => void | — | Called when the open state changes |
openDelay | number | 300 | ms to wait before opening on hover |
closeDelay | number | 200 | ms to wait before closing after leaving |
Trigger props
The Trigger renders a <span> and accepts all standard <span> HTML attributes. It manages onMouseEnter, onMouseLeave, onFocus, and onBlur internally (your handlers are still called).
Content props
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Side of the trigger to render on |
sideOffset | number | 8 | Gap in px between trigger and card |
forceMount | boolean | false | Keep the card mounted while closed (for CSS exit animations) |
Content also accepts all standard <div> HTML attributes.
Data attributes
| Attribute | Element | Values |
|---|---|---|
data-state | Trigger, Content | "open" / "closed" |
data-side | Content | "top" / "right" / "bottom" / "left" |
Content sets role="dialog".
Accessibility
- Content renders with
role="dialog". - Opens immediately on Trigger focus and closes on blur, so keyboard users can reach interactive content inside the card.
- Pointer users can move from the Trigger into the Content without it closing — the close timer is cancelled while hovering the card.
Keyboard Interactions
| Key | Description |
|---|---|
| Tab | Moves focus to the trigger, opening the card immediately. |
| Shift+Tab | Moves focus away from the trigger, closing the card. |