Overlays/Hover Card

Hover Card

For sighted users to preview content behind a link.

Themed

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

  • Brief text hints or labels - use Tooltip instead
  • Interactive content requiring clicks (forms, buttons) - use Popover
  • Critical information that must be accessible to keyboard-only users - hover cards are pointer-only
  • Content that should persist after the pointer leaves - use Dialog or Sheet

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 asChild with a link or button to ensure proper role semantics
  • Add role="region" and aria-label on 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>

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.

PropTypeDefaultDescription
openbooleanControlled open state of the hover card.
onOpenChange(open: boolean) => voidEvent handler called when the open state changes.
defaultOpenbooleanfalseThe open state when initially rendered (uncontrolled).
openDelaynumber700Delay in milliseconds before the hover card opens.
closeDelaynumber300Delay in milliseconds before the hover card closes.

HoverCardTrigger

The element that activates the hover card on pointer enter.

PropTypeDefaultDescription
asChildbooleanfalseWhen true, the trigger renders its child element as the root, merging props and behavior.
classNamestringAdditional CSS classes to apply to the trigger.

HoverCardContent

The floating content panel rendered in a portal. Accepts positioning and alignment props.

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"The preferred side of the trigger to render against.
sideOffsetnumber4Distance in pixels from the trigger element.
align"start" | "center" | "end""center"Alignment of the content relative to the trigger.
avoidCollisionsbooleantrueWhen true, overrides side and align to prevent collisions with viewport edges.
classNamestringAdditional CSS classes to apply to the content.