Skip to content

Hover Card

Stable

A preview of the content behind a link — a person, a repository, a page — shown when the link is hovered or focused.

Reviewed by @grace 2 hours ago

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/hover-card.json

Usage

import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "@/components/ui/hover-card"
<HoverCard>
  <HoverCardTrigger href="/people/grace">@grace</HoverCardTrigger>
  <HoverCardContent>{/* profile preview */}</HoverCardContent>
</HoverCard>

HoverCardTrigger renders a real <a>: the preview is an enhancement of a link that works on its own. It's built on the Base UI Preview Card.

Examples

Issue preview

References to issues, pull requests and documents are good candidates: the card answers what is this and is it done? without a click. Keep it to identity, status, and one or two lines of context.

Fixed in DAT-1284, shipped in v1.4.2.

Preview where an external link leads before people commit to leaving the page. Here the card opens above the link (side="top") and uses a tinted footer for metadata.

prfct is built on mui/base-ui, the unstyled primitives from the teams behind Radix, Floating UI and Material UI.

Delay

delay (600ms by default) and closeDelay (300ms) on the trigger decide how intentional a hover must be. Long delays prevent cards from flashing as the pointer crosses a page; short ones suit dense lists that people scan on purpose.

Guidelines

When to use

  • To preview the destination of a link: a person, an issue, a repository, a document.
  • When the preview helps people decide whether to navigate, without making them navigate.

When not to use

  • For essential information — hover cards are invisible on touch devices and easy to miss. Put it on the page.
  • For interactive tasks — use a Popover, which opens on click and can hold forms.
  • For a one-line label — use a Tooltip.

A preview, not a page

The card should confirm this is what you're looking for. If you find yourself adding tabs, lists or several actions, link to a page instead.

GH
Grace HopperCompiler engineer · Arlington
Do.Identity and a line of context, then get out of the way.
Grace Hopper
Don’t.A dashboard in a hover card disappears the moment the pointer slips.

Accessibility

A hover card is a visual enhancement for sighted pointer and keyboard users. It opens when the link is hovered and when it receives keyboard focus, but it isn't announced and the link doesn't reference it, so screen reader users experience the link on its own. Treat the card as optional context.

KeyBehavior
Tab
Focusing the link opens the card after the delay.
Enter
Follows the link.
Esc
Closes the card.
  • The link must stand on its own. Its text should say where it goes; the card only adds context.
  • Don't hide essentials in it. Anything people must know or do can't live only in a hover card.
  • Hoverable. Moving the pointer from the link onto the card keeps it open, within the closeDelay.

API reference

HoverCard

The root. Doesn't render an element. Accepts every prop of Base UI PreviewCard.Root.

PropTypeDefault
open

Whether the card is open. Use with onOpenChange to control it.

booleanNo default
defaultOpen

Whether it is open initially, when uncontrolled.

booleanfalse
onOpenChange

Called when it opens or closes.

(open: boolean, details) => voidNo default
actionsRef

Imperative handle to close or unmount the card.

RefObject<{ close, unmount }>No default

HoverCardTrigger

The link that opens the card. Renders an <a> and accepts every anchor attribute.

PropTypeDefault
hrefrequired

Where the link goes. The card is a preview of this destination.

stringNo default
delay

How long the pointer must rest on the link before the card opens, in ms.

number600
closeDelay

How long to wait before closing after the pointer leaves, in ms.

number300

HoverCardContent

Renders the portal, positioner and popup.

PropTypeDefault
side

Preferred side of the link. Flips when it doesn't fit.

"top" | "right" | "bottom" | "left" | "inline-start" | "inline-end""bottom"
sideOffset

Distance from the link, in px.

number6
align

Alignment against the link.

"start" | "center" | "end""center"
alignOffset

Offset along the alignment axis, in px.

number0
className

Merged with the popup classes. The default width is w-72.

stringNo default