- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Card
- Checkbox
- Collapsible
- Combobox
- Context Menu
- Date Picker (Lite)
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP (Lite)
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
import { Button } from "@/components/ui/button"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
export default function HoverCardDemo() {
return (
<HoverCard>
<HoverCardTrigger
delay={10}
closeDelay={100}
render={<Button variant="link" />}
>
Hover Here
</HoverCardTrigger>
<HoverCardContent class="flex w-64 flex-col gap-0.5">
<div class="font-semibold">@nextjs</div>
<div>The React Framework – created and maintained by @vercel.</div>
<div class="mt-1 text-xs text-muted-foreground">
Joined December 2021
</div>
</HoverCardContent>
</HoverCard>
)
}Installation
pnpm dlx shadcnui-hono-jsx@latest add hover-cardnpx shadcnui-hono-jsx@latest add hover-cardyarn dlx shadcnui-hono-jsx@latest add hover-cardbunx shadcnui-hono-jsx@latest add hover-cardThis component uses a small client script. add installs it into public/shadcn/; serve that directory at /shadcn/ and load the script on pages that use the component (see Client Scripts):
<script type="module" src="/shadcn/hover.js"></script>Usage
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent>
The React Framework – created and maintained by @vercel.
</HoverCardContent>
</HoverCard>Composition
Use the following composition to build a HoverCard:
HoverCard
├── HoverCardTrigger
└── HoverCardContentTrigger Delays
Use delay and closeDelay on the trigger to control when the card opens and
closes.
<HoverCard>
<HoverCardTrigger delay={100} closeDelay={200}>
Hover
</HoverCardTrigger>
<HoverCardContent>Content</HoverCardContent>
</HoverCard>Positioning
Use the side and align props on HoverCardContent to control placement.
<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent side="top" align="start">
Content
</HoverCardContent>
</HoverCard>Basic
import { Button } from "@/components/ui/button"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
export default function HoverCardDemo() {
return (
<HoverCard>
<HoverCardTrigger
delay={10}
closeDelay={100}
render={<Button variant="link" />}
>
Hover Here
</HoverCardTrigger>
<HoverCardContent class="flex w-64 flex-col gap-0.5">
<div class="font-semibold">@nextjs</div>
<div>The React Framework – created and maintained by @vercel.</div>
<div class="mt-1 text-xs text-muted-foreground">
Joined December 2021
</div>
</HoverCardContent>
</HoverCard>
)
}Sides
Hover Card
This hover card appears on the left side of the trigger.
Hover Card
This hover card appears on the top side of the trigger.
Hover Card
This hover card appears on the bottom side of the trigger.
Hover Card
This hover card appears on the right side of the trigger.
import { Button } from "@/components/ui/button"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
const HOVER_CARD_SIDES = ["left", "top", "bottom", "right"] as const
export function HoverCardSides() {
return (
<div class="flex flex-wrap justify-center gap-2">
{HOVER_CARD_SIDES.map((side) => (
<HoverCard key={side}>
<HoverCardTrigger
delay={100}
closeDelay={100}
render={<Button variant="outline" class="capitalize" />}
>
{side}
</HoverCardTrigger>
<HoverCardContent side={side}>
<div class="flex flex-col gap-1">
<h4 class="font-medium">Hover Card</h4>
<p>This hover card appears on the {side} side of the trigger.</p>
</div>
</HoverCardContent>
</HoverCard>
))}
</div>
)
}RTL
To enable RTL support in shadcn/ui, see the RTL configuration guide.
// This example sets dir and uses useTranslation because this site is not RTL.
// In an RTL app you won't need them; see the RTL guide.
import {
type Translations,
useTranslation,
} from "@/components/language-selector"
import { Button } from "@/components/ui/button"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
const translations: Translations = {
en: {
dir: "ltr",
values: {
trigger: "Wireless Headphones",
name: "Wireless Headphones",
price: "$99.99",
"inline-start": "Inline Start",
left: "Left",
top: "Top",
bottom: "Bottom",
right: "Right",
"inline-end": "Inline End",
},
},
ar: {
dir: "rtl",
values: {
trigger: "سماعات لاسلكية",
name: "سماعات لاسلكية",
price: "٩٩.٩٩ $",
"inline-start": "بداية السطر",
left: "يسار",
top: "أعلى",
bottom: "أسفل",
right: "يمين",
"inline-end": "نهاية السطر",
},
},
he: {
dir: "rtl",
values: {
trigger: "אוזניות אלחוטיות",
name: "אוזניות אלחוטיות",
price: "99.99 $",
"inline-start": "תחילת השורה",
left: "שמאל",
top: "למעלה",
bottom: "למטה",
right: "ימין",
"inline-end": "סוף השורה",
},
},
}
const physicalSides = ["left", "top", "bottom", "right"] as const
const logicalSides = ["inline-start", "inline-end"] as const
export function HoverCardRtl() {
const { dir, t } = useTranslation(translations, "ar")
return (
<div class="grid gap-4">
<div class="flex flex-wrap justify-center gap-2">
{physicalSides.map((side) => (
<HoverCard key={side}>
<HoverCardTrigger
delay={10}
closeDelay={100}
render={<Button variant="outline" />}
>
{t[side]}
</HoverCardTrigger>
<HoverCardContent
side={side}
class="flex w-64 flex-col gap-1"
dir={dir}
>
<div class="font-semibold">{t.name}</div>
<div class="text-sm text-muted-foreground">{t.price}</div>
</HoverCardContent>
</HoverCard>
))}
</div>
<div class="flex flex-wrap justify-center gap-2">
{logicalSides.map((side) => (
<HoverCard key={side}>
<HoverCardTrigger
delay={10}
closeDelay={100}
render={<Button variant="outline" />}
>
{t[side]}
</HoverCardTrigger>
<HoverCardContent
side={side}
class="flex w-64 flex-col gap-1"
dir={dir}
>
<div class="font-semibold">{t.name}</div>
<div class="text-sm text-muted-foreground">{t.price}</div>
</HoverCardContent>
</HoverCard>
))}
</div>
</div>
)
}Notes
- Opening on hover or keyboard focus needs the client script
/shadcn/hover.js(<script type="module" src="/shadcn/hover.js">); without it the card does not open and the trigger works as a plain link. The card is a native popover placed with CSS anchor positioning. - Controlled state (
open,onOpenChange) is not supported. - Accepts
classinstead ofclassName. - Upstream documentation: shadcn/ui Hover Card. See also Differences from shadcn/ui.
API Reference
See the Base UI documentation for more information.