Hover Card
A popover preview anchored to a trigger, shown on pointer hover—profiles, link previews, and lightweight context.
Installation
Hover Card is exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.
Composition
Use HoverCard as the root with HoverCardTrigger and HoverCardContent:
HoverCard
├── HoverCardTrigger
└── HoverCardContentHover Card is for richer previews than a Tooltip (short text). The panel can include short structured content; avoid long forms or critical-only actions here. Behavior follows Radix UI Hover Card.
Usage
import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from '@by/experience-system';Hover Card primitives (HoverCard, HoverCardTrigger, HoverCardContent) are client components ('use client'). Wrap your tree in ThemeProvider so HoverCardContent can resolve the portal container. Use it inside a Client Component or a dynamic import when using the Next.js App Router.
<HoverCard openDelay={10} closeDelay={100}>
<HoverCardTrigger asChild>
<Button variant="ghost">Hover here</Button>
</HoverCardTrigger>
<HoverCardContent className="flex flex-col gap-scaled-2">
<div className="font-medium">Title</div>
<div>Supporting text.</div>
</HoverCardContent>
</HoverCard>When to use
- Optional contextual detail that helps understanding but is not required to complete the task.
- Dense UIs where in-place detail would add noise (tables, dashboards, feeds).
- Helpful, non-critical metadata (summaries, definitions).
- Desktop-first experiences where cursor hover is common.
When not to use
- Critical information or actions that must not depend on hover alone.
- Touch-first layouts without a reliable hover affordance—prefer tap targets, popovers, or sheets.
- High-frequency actions that should stay visible or one click away.
- Large or complex content—use a page, Dialog, or Drawer instead.
Examples
The live preview at the top of this page uses hover-card-overview. Shorter openDelay / closeDelay values feel responsive in demos; increase them in dense UIs to reduce accidental activation.
API Reference
Subsection titles name @by/experience-system exports and the Radix part they wrap. Full primitive reference: Radix Hover Card.
HoverCard
| Prop | Type | Default |
|---|---|---|
open | boolean | — |
defaultOpen | boolean | — |
onOpenChange | (open: boolean) => void | — |
openDelay | number | — |
closeDelay | number | — |
Also accepts other HoverCard.Root props from Radix.
HoverCardTrigger
The anchor that opens the card on hover or focus; supports asChild.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
HoverCardContent
Floating panel; portaled with useContainerElement. Default align="center", sideOffset={4} in this experience system; merges className with card, border, shadow, and motion utilities.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
forceMount | boolean | — |
Also accepts Radix content positioning props (side, align, sideOffset, collisionPadding, …). See Radix — Content.
Accessibility
The trigger should be a real control (for example Button or Link) so keyboard users can move focus to it and open the card per Radix — accessibility. Keep preview content concise; if users must operate controls inside the panel, consider Popover or Dialog instead.
Source in the repo: packages/experience-system/src/components/HoverCard/HoverCard.tsx. Agent-oriented contracts: packages/experience-system/src/components/HoverCard/HoverCard.instructions.md.