Hover Card
A preview that opens when a link or button is hovered or focused.
Overview
HoverCardTrigger clones one child. Hover, or keyboard focus, opens HoverCardContent. Moving onto the card keeps it open. Escape closes it. There is no asChild prop.
Preview
Customize
Installation
Add the component with the CLI. It copies the files in and installs anything they depend on.
npx vinyaas add hover-cardUsage
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card";
export function ProfileCard() {
return (
<HoverCard>
<HoverCardTrigger>
<Button variant="link" className="underline underline-offset-4">
@johndoe
</Button>
</HoverCardTrigger>
<HoverCardContent>
<div className="flex items-start gap-3 text-left">
<Avatar>
<AvatarFallback>JD</AvatarFallback>
</Avatar>
<div className="grid gap-1">
<p className="font-medium">John Doe</p>
<p className="text-muted-foreground text-sm">@johndoe</p>
<p className="text-sm">
Product designer building accessible UI for design systems.
</p>
<div className="flex flex-wrap items-center gap-2 pt-1">
<Badge variant="outline">Maintainer</Badge>
<span className="text-muted-foreground text-xs">San Francisco</span>
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>
);
}Examples
Profile
Hover or focus an @username to read a short profile. The card stays open while the pointer is over it.
Alignment
side places the card above, below, or beside the trigger. The grid wraps on small screens so the triggers stay usable.
In practice
An assignment line links @johndoe. Hover or focus the mention to open a profile with Avatar, role, and bio.
Assigned to
API
Other attributes for the underlying element are passed through.
| Name | Type | Default | Description |
|---|---|---|---|
openDelay | number | 200 | Milliseconds before hover or focus opens the card. |
closeDelay | number | 150 | Milliseconds before the pointer leaving closes the card. |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Called when the card opens or closes. |
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side for HoverCardContent. |
className | string | — | Merged onto HoverCardContent with cn. |
Accessibility
The trigger exposes aria-expanded, aria-haspopup="dialog", and aria-controls while the card is open. The card is a non-modal dialog. Escape closes it. Focus on the trigger opens it, so keyboard users reach the same content as pointer users.