Hover Card
For sighted users to preview content behind a link.
When to Use
Use Hover Card when you need to:
- Preview user profile information on username mentions
- Show link previews before the user navigates away
- Display quick info cards for items in lists or tables
- Provide rich contextual previews for tags, labels, or categories
- Show supplementary details that do not require user interaction
When Not to Use
Default
Hover card with avatar and user profile information.
Simple
Basic hover card with text-only content for lightweight previews.
Positions
Hover card can be positioned on any side of the trigger using the side prop.
<HoverCard openDelay={200} closeDelay={100}>
<HoverCardTrigger asChild>
<Button variant="link">Quick hover</Button>
</HoverCardTrigger>
<HoverCardContent>
Opens faster, closes faster
</HoverCardContent>
</HoverCard>const [open, setOpen] = React.useState(false)
<HoverCard open={open} onOpenChange={setOpen}>
<HoverCardTrigger asChild>
<Button variant="link">Controlled</Button>
</HoverCardTrigger>
<HoverCardContent>
Controlled hover card content
</HoverCardContent>
</HoverCard>UX & Design Guidelines
Content Strategy
Keep hover card content concise and scannable. Include only preview-level information (avatar, name, short bio, key metadata). Avoid placing interactive controls inside hover cards - if the user needs to take action, use a Popover instead. The content should give enough context to decide whether to click through.
Timing & Delays
The default openDelay=700 prevents accidental triggers when the pointer sweeps across the page. The closeDelay=300 gives users time to move the pointer into the card content. Avoid reducing openDelay below 200ms or users will see unwanted flashes. Increase delays for dense lists with many triggers.
Responsive Behavior
Hover cards are a pointer-centric pattern and are not triggered on touch devices. Ensure the content behind the hover card is still accessible through the trigger link or an alternative navigation path. On smaller viewports, the card automatically repositions with avoidCollisions to stay within the viewport.
Color & Contrast
The hover card uses bg-popover with text-popover-foreground for consistent contrast across light and dark modes. The shadow and border ensure the card is visually distinct from the page surface. Avoid custom background colors that may break contrast ratios.
Accessibility
Pointer-Only Pattern
Hover cards are designed for sighted pointer users. They do not respond to keyboard focus or touch events by default. Any information shown exclusively in a hover card should also be reachable via the trigger link itself. For keyboard-accessible supplementary information, use Tooltip (which responds to focus).
Keyboard Navigation
- Tab — Moves focus to the trigger element (does not open the card)
- Enter — Activates the trigger (e.g., follows the link); does not open the card
- Esc — Closes the hover card if it is open
Screen Reader Support
- The trigger announces its accessible name (text content or
aria-label) - Hover card content is not announced to screen readers - it is supplementary information for sighted users
- Use
asChildwith a link or button to ensure proper role semantics - Add
role="region"andaria-labelon content if it contains critical supplementary info
Motion & Reduced Motion
The hover card uses fade and zoom animations on open/close. These animations automatically respect the prefers-reduced-motion media query. When reduced motion is preferred, the card appears and disappears instantly without transitions.
ARIA Attributes
{/* Trigger with descriptive content */}
<HoverCard>
<HoverCardTrigger asChild>
<a href="/user/nextjs" className="underline">
@nextjs
</a>
</HoverCardTrigger>
<HoverCardContent>
<p>Profile preview for @nextjs</p>
</HoverCardContent>
</HoverCard>
{/* Using asChild to preserve semantic HTML */}
<HoverCard>
<HoverCardTrigger asChild>
<Button variant="link" aria-label="Preview Next.js profile">
@nextjs
</Button>
</HoverCardTrigger>
<HoverCardContent>
<div role="region" aria-label="User profile preview">
<h4 className="text-sm font-semibold">@nextjs</h4>
<p className="text-sm">The React Framework</p>
</div>
</HoverCardContent>
</HoverCard>Related Components
Tooltip
Simple text hint on hover or focus. Keyboard-accessible alternative for brief labels.
Popover
Click-triggered floating panel for interactive content like forms and menus.
Card
Static content container with header, body, and footer for inline information display.
Dialog
Modal overlay for content that requires user attention or interaction to dismiss.
API Reference
The Hover Card is composed of three parts: the root wrapper, a trigger, and the content panel.
HoverCard
Root component that manages open state and delay timing.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state of the hover card. |
| onOpenChange | (open: boolean) => void | — | Event handler called when the open state changes. |
| defaultOpen | boolean | false | The open state when initially rendered (uncontrolled). |
| openDelay | number | 700 | Delay in milliseconds before the hover card opens. |
| closeDelay | number | 300 | Delay in milliseconds before the hover card closes. |
HoverCardTrigger
The element that activates the hover card on pointer enter.
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | When true, the trigger renders its child element as the root, merging props and behavior. |
| className | string | — | Additional CSS classes to apply to the trigger. |
HoverCardContent
The floating content panel rendered in a portal. Accepts positioning and alignment props.
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "bottom" | The preferred side of the trigger to render against. |
| sideOffset | number | 4 | Distance in pixels from the trigger element. |
| align | "start" | "center" | "end" | "center" | Alignment of the content relative to the trigger. |
| avoidCollisions | boolean | true | When true, overrides side and align to prevent collisions with viewport edges. |
| className | string | — | Additional CSS classes to apply to the content. |