Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
import { CalendarDays } from "lucide-react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
export const HoverCardDemo = () => (
<HoverCard>
<HoverCardTrigger asChild><Button variant="link">@nextjs</Button></HoverCardTrigger>
<HoverCardContent className="w-80">
<div className="flex justify-between gap-4">
<Avatar>
<AvatarImage src="https://github.com/vercel.png" />
<AvatarFallback>VC</AvatarFallback>
</Avatar>
<div className="space-y-1">
<h4 className="text-sm font-semibold">@nextjs</h4>
<p className="text-sm text-muted-foreground">The React Framework — created and maintained by @vercel.</p>
<div className="flex items-center gap-2 pt-2">
<CalendarDays className="size-4 text-muted-foreground" />
<span className="text-xs text-muted-foreground">Joined December 2021</span>
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>
);Custom delay
Control how quickly the card opens and closes with openDelay and closeDelay (milliseconds). The default is 700ms open / 300ms close.
{/* Opens faster, stays open longer */}
<HoverCard openDelay={200} closeDelay={500}>
<HoverCardTrigger asChild>
<Button variant="link">@username</Button>
</HoverCardTrigger>
<HoverCardContent>...</HoverCardContent>
</HoverCard>Placement
Use side and align on HoverCardContent to control positioning relative to the trigger.
{/* Above the trigger, right-aligned */}
<HoverCardContent side="top" align="end">
...
</HoverCardContent>With image preview
import { ExternalLink } from "lucide-react";
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
<HoverCard>
<HoverCardTrigger asChild>
<a href="#" className="text-sm font-medium underline underline-offset-4">
GIN Design
</a>
</HoverCardTrigger>
<HoverCardContent side="top" className="w-72">
<div className="space-y-2">
<div className="h-32 rounded-md bg-muted" />
<div className="space-y-1">
<p className="text-sm font-semibold">GIN Design System</p>
<p className="text-xs text-muted-foreground">
A custom component registry built on shadcn/ui.
</p>
</div>
<div className="flex items-center gap-1 text-xs text-muted-foreground">
<ExternalLink className="size-3" />
gin-design.vercel.app
</div>
</div>
</HoverCardContent>
</HoverCard>Props
HoverCard
| Prop | Type | Default | Description |
|---|---|---|---|
openDelay | number | 700 | Milliseconds before the card opens |
closeDelay | number | 300 | Milliseconds before the card closes after hover leaves |
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Uncontrolled initial state |
onOpenChange | (open: boolean) => void | — | Callback when state changes |
HoverCardContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side to render |
align | "start" | "center" | "end" | "center" | Alignment along the trigger |
sideOffset | number | 4 | Gap between trigger and card |
className | string | — | Default width is w-64 — override with w-80 etc. |
Usage
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card";
<HoverCard>
<HoverCardTrigger asChild>
<Button variant="link">Hover me</Button>
</HoverCardTrigger>
<HoverCardContent>
<p className="text-sm">Card content here.</p>
</HoverCardContent>
</HoverCard>Specs
# Mint — Hover Card Specs
## Component
- name: hover-card
- file: registry/mint/hover-card.tsx
- installs to: components/ui/hover-card.tsx
- dependencies: radix-ui
- registryDependencies: none
## What is it
A floating panel that opens on pointer hover or keyboard focus of a trigger element
and closes when the pointer leaves both the trigger and the content area. Use it to
preview richer content — profiles, links, images — without requiring a click or
navigation. Prefer Popover over HoverCard for touch surfaces or interactive actions.
## Visual identity
Popover-surface background with a subtle border and medium drop shadow (shadow-md),
giving a clean elevated card feel. Standard border radius (rounded-md) and 16px
padding create a balanced, readable container. Animates in/out with a combined
fade + zoom + directional slide keyed to the open side.
## Design tokens
--popover: oklch(1 0 0) / oklch(0.269 0 0) — card surface (light/dark)
--popover-foreground: oklch(0.145 0 0) / oklch(0.985 0 0) — text on card
--border: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%) — card border
## Sub-components
- HoverCard → root provider; accepts openDelay (default 700ms) and closeDelay (default 300ms)
- HoverCardTrigger → wraps the hover target; use asChild to preserve element semantics
- HoverCardContent → floating panel rendered in a Portal; w-64 p-4 rounded-md border shadow-md
## States
- data-[state=open]: fade-in-0 + zoom-in-95 + slide-in-from-{side}-2 (enter animation)
- data-[state=closed]: fade-out-0 + zoom-out-95 (exit animation)
- data-[side=bottom]: slide-in-from-top-2
- data-[side=top]: slide-in-from-bottom-2
- data-[side=left]: slide-in-from-right-2
- data-[side=right]: slide-in-from-left-2
## Conventions
- Use asChild on HoverCardTrigger to avoid adding an extra DOM element and preserve semantics
- HoverCardContent renders in a Portal (z-50) — add a z-* override if it clips behind other layers
- Default width is w-64 (256px); override with className="w-72" or "w-80" on HoverCardContent
- Tune openDelay for context: shorter (200–300ms) for dense scan UIs, longer (700ms default) for reading surfaces
- Do not place critical or irreversible actions inside HoverCard — hover is not reliably accessible on touch devices; use Popover with a click trigger instead
- Sub-components expose data-slot="hover-card", data-slot="hover-card-trigger", and data-slot="hover-card-content" for CSS targetingInstallation
$ npx shadcn add \https://gin-design.vercel.app/hover-card