Hover Card
A contextual popup that appears on hover, perfect for previewing content, user profiles, and additional information without leaving the current page.
You know when you're scrolling Twitter and hover over someone's name to see their bio? That's what hover cards do - show useful info without making you click away and lose your place.
Rich profile preview
Hover to see detailed user information:
Built on Radix UI, so the positioning and accessibility stuff is handled. Works with mouse, keyboard, whatever.
npx shadcn@latest add hover-card
Why hover cards just work
Ever been scared to click a link because you don't know where it goes? Or had to open a new tab just to check someone's profile? Hover cards fix that - you get a quick peek without losing your spot.
Essential hover card patterns you'll use
Simple content preview
Just the basics:
Detailed user profile
Full profile with follower counts and all that:
Product previews
Quick product info before they click:
Link previews
So you know what you're about to click:
Status and metrics
Server status, performance metrics, that stuff:
API Reference
HoverCard
Root component that manages hover card state and positioning.
Prop | Type | Default | Description |
---|---|---|---|
open | boolean | - | Whether the hover card is open |
onOpenChange | (open: boolean) => void | - | Callback when open state changes |
defaultOpen | boolean | false | Default open state (uncontrolled) |
openDelay | number | 700 | Delay before opening (milliseconds) |
closeDelay | number | 300 | Delay before closing (milliseconds) |
children | React.ReactNode | - | HoverCardTrigger and HoverCardContent |
HoverCardTrigger
Element that triggers the hover card when hovered or focused.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Render as child element instead of button |
children | React.ReactNode | - | Trigger content |
HoverCardContent
The popup content that appears on hover or focus.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes |
align | "start" | "center" | "end" | "center" | Alignment relative to trigger |
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side to open |
sideOffset | number | 4 | Distance from trigger element |
alignOffset | number | 0 | Offset from align position |
avoidCollisions | boolean | true | Prevent collisions with viewport edges |
collisionBoundary | Element | Element[] | [] | Boundary elements for collision detection |
sticky | "partial" | "always" | "partial" | Sticky positioning behavior |
children | React.ReactNode | - | Card content |
Timing Configuration
Delay Type | Default | Description | Best Practice |
---|---|---|---|
openDelay | 700ms | Time before showing card | 500-1000ms for comfortable UX |
closeDelay | 300ms | Time before hiding card | 200-500ms to prevent flicker |
Positioning Options
Side | Description | Use Cases |
---|---|---|
top | Opens above trigger | Bottom navigation, footers |
bottom | Opens below trigger | Default, most menu items |
left | Opens to the left | Right-aligned content |
right | Opens to the right | Left-aligned content, sidebars |
Alignment Options
Align | Description | Visual Result |
---|---|---|
start | Aligns to start edge | Left-aligned for horizontal, top for vertical |
center | Centers on trigger | Balanced positioning |
end | Aligns to end edge | Right-aligned for horizontal, bottom for vertical |
Interaction States
State | Trigger | Duration |
---|---|---|
Idle | No interaction | - |
Pending Open | Hover/focus starts | openDelay duration |
Open | Card visible | Until leave/blur + closeDelay |
Pending Close | Leave/blur starts | closeDelay duration |
Closed | Card hidden | - |
Accessibility Features
Feature | Implementation |
---|---|
Keyboard Support | Opens on focus, closes on blur/escape |
ARIA Attributes | Proper labeling and describedby relationships |
Focus Management | Maintains focus trap when needed |
Screen Readers | Announces content changes appropriately |
High Contrast | Respects system color preferences |
Reduced Motion | Honors user motion preferences |
Common patterns that work
User profiles - Perfect for @mentions, author credits, or team member lists. Show avatar, bio, join date, and social stats without leaving the page.
Product previews - Let users peek at items before clicking through. Include images, ratings, prices, and quick action buttons.
Link previews - Give context for external links. Show site info, descriptions, and trust indicators so users know what they're clicking.
Status displays - Surface system health, performance metrics, or feature availability with rich context on hover.
Make hover cards that actually help
The best hover cards feel invisible until you need them. Here's how to nail that:
- Show stuff people care about - Profile cards with follower counts, not just names
- Time it right - Too fast feels jumpy, too slow feels broken (700ms is usually perfect)
- Size for content - Big enough to be useful, small enough to not dominate the screen
- Make it scannable - Good typography hierarchy so people find what they need fast
- Add useful actions - Follow buttons, add to cart, copy links - stuff people actually want to do
- Don't break on mobile - Touch devices are tricky, have a backup plan
- Keep it snappy - Nobody wants to wait 3 seconds for a profile picture to load
- Stay predictable - If cards pop up from different directions, it's confusing
- Easy escape - Click outside, hit escape, whatever - make it obvious how to close them
Form
Build accessible, type-safe forms with React Hook Form and Zod validation. Composable components that handle state, validation, and accessibility automatically.
Input OTP
A one-time password input component for React and Next.js. Perfect for 2FA authentication, verification codes, and secure login flows with shadcn/ui styling.