Hover Card
For sighted users to preview content available behind a link.
Installation
bash
npx shadcn@latest add @redpanda/hover-cardbash
pnpm dlx shadcn@latest add @redpanda/hover-cardbash
yarn dlx shadcn@latest add @redpanda/hover-cardbash
bunx shadcn@latest add @redpanda/hover-cardbash
nubx shadcn@latest add @redpanda/hover-cardbash
aube dlx shadcn@latest add @redpanda/hover-cardPositioning
When to use
Use this decision tree to determine when to use the Hover Card component:
Usage
tsx
<HoverCard> <HoverCardTrigger>Hover Card Trigger</HoverCardTrigger> <HoverCardContent>Hover Card Content</HoverCardContent></HoverCard>Props
Keyboard interactions
| Key | Action |
|---|---|
Tab to HoverCardTrigger |
Opens the hover card (keyboard-focus trigger). |
Shift+Tab off the trigger |
Closes the hover card. |
Escape |
Closes the hover card without moving focus. |
| Pointer hover / leave | Opens after openDelay, closes after closeDelay. |
Accessibility
- Hover cards are supplementary — put the same content on the page in an accessible form (link target, expandable section) so touch and reduced-motion users aren’t excluded.
- The trigger must be a focusable element (
<a href>is typical since hover cards preview links). Use therenderprop to render the trigger as whatever semantic element you need. - Content is wired via
aria-describedbyso screen readers announce the preview when the trigger has focus. - Prefer
Popoverwhen the content contains interactive controls — hover cards auto-close on leave and interactive content becomes difficult to reach.
Controlled vs uncontrolled
Uncontrolled — typical case, hover cards time their own open/close:
tsx
<HoverCard> <HoverCardTrigger render={<a href="/users/bm">@malinskibeniamin</a>} /> <HoverCardContent>{/* preview card */}</HoverCardContent></HoverCard>Controlled — force open/closed for demos or during a guided tour:
tsx
const [open, setOpen] = useState(false);
<HoverCard open={open} onOpenChange={setOpen}> <HoverCardTrigger render={<a href="/users/bm">@malinskibeniamin</a>} /> <HoverCardContent>{/* preview card */}</HoverCardContent></HoverCard>;