Unified UI

Hover Card

A rich preview card that appears on hover. Built on Radix UI HoverCard with scaleIn animation, configurable open/close delay, and arrow indicator.

Basic

A rich preview card that floats above content on hover. Ideal for user profiles, link previews, and contextual information panels. Built on Radix UI with a spring scaleIn entrance animation.

Installation

Install the component via the CLI in one command.

npx @work-rjkashyap/unified-ui add hover-card
pnpm dlx @work-rjkashyap/unified-ui add hover-card
npx @work-rjkashyap/unified-ui add hover-card
bunx @work-rjkashyap/unified-ui add hover-card

If you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for details.

Or install the full package

Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.

npm install @work-rjkashyap/unified-ui
pnpm add @work-rjkashyap/unified-ui
yarn add @work-rjkashyap/unified-ui
bun add @work-rjkashyap/unified-ui

Anatomy

import {
	HoverCard,
	HoverCardTrigger,
	HoverCardContent,
	Avatar,
	Button,
	Badge,
} from "@work-rjkashyap/unified-ui";

Basic Usage

Wrap a trigger in HoverCardTrigger and your preview content in HoverCardContent. The card opens after a 200ms delay and closes after 150ms — preventing accidental triggers from quick cursor passes.

<HoverCard>
	<HoverCardTrigger asChild>
		<a href="/profile" className="underline text-primary">
			@username
		</a>
	</HoverCardTrigger>
	<HoverCardContent>
		<p className="text-sm">Preview content goes here.</p>
	</HoverCardContent>
</HoverCard>

Placement

Use the side and align props on HoverCardContent to control where the card appears relative to the trigger.

sidePosition
topAbove the trigger
bottomBelow the trigger (default)
leftTo the left of the trigger
rightTo the right of the trigger
alignAlignment along the cross axis
startAligned to the start edge of the trigger
centerCentered against the trigger (default)
endAligned to the end edge of the trigger

Open & Close Delay

Control how long the user must hover before the card opens (openDelay) and how long before it closes when the cursor leaves (closeDelay).

{
	/* Opens quickly, stays open longer */
}
<HoverCard openDelay={100} closeDelay={300}>
	<HoverCardTrigger asChild>
		<span className="underline cursor-help">Quick open</span>
	</HoverCardTrigger>
	<HoverCardContent>
		<p className="text-sm">Opens after 100ms, closes after 300ms.</p>
	</HoverCardContent>
</HoverCard>;

{
	/* Default delays */
}
<HoverCard openDelay={200} closeDelay={150}>
	...
</HoverCard>;

The delay prevents the card from flickering when the cursor briefly passes over the trigger while moving to other elements.

User Profile Card

A rich user profile preview — the most common HoverCard pattern.

Posted by · 2 hours ago

Show a preview card for external or internal links on hover.

Custom Width

The default card width is w-64 (256px). Override it with a className on HoverCardContent.

{
	/* Narrower */
}
<HoverCardContent className="w-48">...</HoverCardContent>;

{
	/* Wider — for rich content */
}
<HoverCardContent className="w-80">...</HoverCardContent>;

{
	/* Auto width based on content */
}
<HoverCardContent className="w-auto">...</HoverCardContent>;

Side Offset

Use sideOffset to control the gap between the trigger and the card.

{
	/* Default: 8px gap */
}
<HoverCardContent sideOffset={8}>...</HoverCardContent>;

{
	/* Tighter: 4px gap */
}
<HoverCardContent sideOffset={4}>...</HoverCardContent>;

{
	/* More breathing room: 12px gap */
}
<HoverCardContent sideOffset={12}>...</HoverCardContent>;

Props

HoverCard

PropTypeDefaultDescription
openDelaynumber200Milliseconds before the card opens after hover.
closeDelaynumber150Milliseconds before the card closes after cursor leaves.
openbooleanControlled open state.
defaultOpenbooleanInitial open state (uncontrolled).
onOpenChange(open: boolean) => voidCallback when the open state changes.

HoverCardTrigger

Uses Radix UI's HoverCardTrigger API. Use asChild to render the trigger as your own element (a <button>, <a>, or any other element).

HoverCardContent

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger to render the card on.
align"start" | "center" | "end""center"Alignment along the cross-axis.
sideOffsetnumber8Pixel gap between the trigger and the card.
classNamestringAdditional CSS classes (use to override width, padding, etc.).
childrenReactNodeThe preview content rendered inside the card.

All other HoverCardContent props are forwarded to the underlying Radix HoverCardContent element.

Motion

  • Open — Uses the scaleIn preset: scale: 0.92 → 1, opacity: 0 → 1 with a spring (stiffness: 300, damping: 24, mass: 0.8).
  • Close — Reverses the scaleIn animation.
  • Arrow — The arrow indicator is rendered by Radix UI and inherits the card's position automatically.
  • All animations respect prefers-reduced-motion via useReducedMotion() — falls back to a simple opacity transition.

Accessibility

  • Built on @radix-ui/react-hover-card — fully WAI-ARIA compliant.
  • The HoverCard is triggered on hover (pointer) and focus (keyboard users can tab to the trigger to see the card).
  • The card content is in a portal, rendered at the document body level, ensuring proper z-index stacking above all page content.
  • HoverCardTrigger asChild preserves the semantics of the host element — an <a> remains an <a>, a <button> remains a <button>.
  • The card is not role="dialog" — it is supplementary preview content, not a focus trap. Do not put critical actions inside a HoverCard.
  • Avoid placing interactive elements (buttons, forms) inside a HoverCard. If interaction is needed, use a Popover instead.

HoverCard vs Tooltip vs Popover

ComponentTriggerContentInteractiveUse Case
TooltipHover/FocusShort text labelNoBrief descriptions for icons/buttons
HoverCardHover/FocusRich previewNo*Profile previews, link previews
PopoverClickRich UIYesFilters, settings, date pickers

*Avoid interactive elements in HoverCard — use Popover for interactive content.

Design Tokens

TokenUsage
--popoverCard background color
--popover-fgCard text color
--borderCard border color
--radius-lgCard border radius
--shadow-lgCard drop shadow
--z-popoverZ-index for the floating card

On this page