Hover Card
Hover-triggered preview pane for non-critical rich content. Built on Radix HoverCard.
Overview
HoverCard shows a rich preview when the user hovers an anchor (link, name, abbreviation). Use it for content the user can fully open with a click but might want a glance at first: user profile cards on @mentions, link previews, document or image teasers.
Never put critical information or interactive controls inside a HoverCard. Hover is unreliable (touch users don't have it; keyboard users only see the card while focus holds) and the preview is supposed to be non-essential. Interactive content belongs in a Popover; simple text labels belong in a Tooltip.
Preview
Installation
bash npx gremorie@latest add rx-hover-card bash pnpm dlx gremorie@latest add rx-hover-card bash yarn dlx gremorie@latest add rx-hover-card bash bunx --bun gremorie@latest add rx-hover-card
Usage
import { Button } from "@gremorie/rx-forms";
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@gremorie/rx-overlays";
export function Example() {
return (
<HoverCard>
<HoverCardTrigger asChild>
<Button variant="link">@gremorie</Button>
</HoverCardTrigger>
<HoverCardContent>
<div className="text-sm">
<strong>Gremorie</strong>
<p className="mt-1 text-muted-foreground">
AI-native design system. Registry + MCP first.
</p>
</div>
</HoverCardContent>
</HoverCard>
);
}Angular edition planned for Phase 5h. Star the repo to track progress.
API
<HoverCard>
Extends Radix HoverCard.Root. Notable props:
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
onOpenChange | (open: boolean) => void | - | Fired when open state changes. |
openDelay | number | 700 | Delay in milliseconds before opening on hover. |
closeDelay | number | 300 | Delay in milliseconds before closing after the pointer leaves. |
<HoverCardTrigger>
Extends Radix HoverCard.Trigger. Pair with asChild to forward styles to a link, button, or any inline anchor.
<HoverCardContent>
| Prop | Type | Default | Description |
|---|---|---|---|
align | "start" | "center" | "end" | "center" | Alignment relative to the trigger axis. |
sideOffset | number | 4 | Pixel gap between trigger and content. |
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side; flips automatically when there is no room. |
Default surface is w-64, padded p-4. Wrapped in a Radix Portal. All other Radix HoverCard.Content props are forwarded.
Composition
<HoverCard>owns hover state. Tune timing withopenDelay/closeDelay.<HoverCardTrigger asChild>wraps the anchor element (typically an inline link or a name).<HoverCardContent>mounts via Portal, anchored to the trigger, fades and zooms in.- Inside content: any non-interactive preview - avatar + bio, image teaser, doc snippet.
Variations
User profile preview
The classic @mention hover card. Triggered by hovering a link to the user's profile.
<HoverCard>
<HoverCardTrigger asChild>
<a href="/users/kalvner" className="font-medium underline">
@kalvner
</a>
</HoverCardTrigger>
<HoverCardContent className="w-72">
<div className="flex gap-3">
<Avatar>
<AvatarImage src="/avatars/kalvner.png" />
<AvatarFallback>BK</AvatarFallback>
</Avatar>
<div className="space-y-1">
<h4 className="text-sm font-semibold">Bruno Kalvner</h4>
<p className="text-xs text-muted-foreground">
Designer and engineer. Maintains Gremorie.
</p>
</div>
</div>
</HoverCardContent>
</HoverCard>Link preview
Show metadata for an external link before the user clicks through.
<HoverCard openDelay={400}>
<HoverCardTrigger asChild>
<a href="https://gremorie.com" className="underline">
gremorie.com
</a>
</HoverCardTrigger>
<HoverCardContent>
<h4 className="text-sm font-semibold">Gremorie</h4>
<p className="text-xs text-muted-foreground">
Registry-driven, MCP-first design system for React and Angular.
</p>
</HoverCardContent>
</HoverCard>Quick image teaser
Use to peek media before committing to a full-screen viewer.
<HoverCard openDelay={200} closeDelay={100}>
<HoverCardTrigger asChild>
<button>Preview thumbnail</button>
</HoverCardTrigger>
<HoverCardContent className="w-80 p-2">
<img src="/teaser.jpg" alt="Teaser" className="rounded-md" />
</HoverCardContent>
</HoverCard>Accessibility
- Trigger: pointer hover and keyboard focus both open the card.
- Keyboard: focusing the trigger opens it; blurring closes it;
Esccloses when focus is inside. - Not for critical content: touch users may never see the card. Keep the content supplementary.
aria-controlsis wired automatically between trigger and content.- No focus trap: pointer can leave naturally; closing returns nothing because the trigger never lost focus by default.
- Reduced motion: open/close animations honor
prefers-reduced-motion.