Glin UI
Primitive / Moleculebeta

Hover Card

Preview card that appears on hover or focus with configurable delays and placement.

Edit on GitHub

Release notes drafted by @avakim and reviewed by the docs team. Hover the handle to see who wrote it.

Installation

Install from
pnpm dlx @glinui/cli@latest add hover-card

Prefer the package?

Usage

A small card previewing the target of an inline link.

See the pricing page for plan details.
"use client"
import {
HoverCard,
HoverCardContent,
HoverCardTrigger
} from "@glinui/ui"
export function HoverCardLinkExample() {
return (
<div className="mx-auto w-full max-w-md text-sm leading-6">
See the{" "}
<HoverCard openDelay={100} closeDelay={80}>
<HoverCardTrigger asChild><a href="#" className="font-medium underline decoration-dotted underline-offset-4">pricing page</a></HoverCardTrigger>
<HoverCardContent className="w-72" size="sm">
<p className="text-sm font-medium">Pricing</p>
<p className="mt-1 text-xs text-[var(--color-muted)]">Free for individuals. Team plans start at $20 per seat each month.</p>
</HoverCardContent>
</HoverCard>{" "}
for plan details.
</div>
)
}

Delays and surface

import { Badge, HoverCard, HoverCardContent, HoverCardTrigger } from "@glinui/ui"
export function Demo() {
return (
<div className="flex flex-wrap items-center gap-4">
<HoverCard openDelay={0} closeDelay={150}>
<HoverCardTrigger asChild>
<button className="text-sm font-medium underline decoration-dotted underline-offset-4">
Instant preview
</button>
</HoverCardTrigger>
<HoverCardContent size="sm">
<div className="space-y-2">
<Badge>default</Badge>
<p className="text-xs text-neutral-600 dark:text-neutral-300">Open delay: 0ms</p>
</div>
</HoverCardContent>
</HoverCard>
<HoverCard openDelay={500} closeDelay={250}>
<HoverCardTrigger asChild>
<button className="text-sm font-medium underline decoration-dotted underline-offset-4">
Delayed preview
</button>
</HoverCardTrigger>
<HoverCardContent variant="plain" size="md">
<p className="text-xs text-neutral-600 dark:text-neutral-300">
Opens after 500ms with the plain surface.
</p>
</HoverCardContent>
</HoverCard>
</div>
)
}

Variants

Every look of the shared vocabulary: glinr (the default), plain (shadcn), solid, soft, outline, ghost, gradient and glass. Omit `variant` to follow the ambient design style.

import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from "@glinui/ui"
const variants = ["glinr", "plain", "solid", "soft", "outline", "ghost", "gradient", "glass"] as const
export function Demo() {
return (
<div className="flex flex-wrap gap-2">
{variants.map((variant) => (
<HoverCard key={variant} openDelay={0}>
<HoverCardTrigger asChild><Button size="sm" variant="outline">{variant}</Button></HoverCardTrigger>
<HoverCardContent variant={variant} size="sm">
<p className="font-medium">{variant} hover card</p>
<p className="mt-1 text-[var(--color-muted)]">Preview on hover or focus.</p>
</HoverCardContent>
</HoverCard>
))}
</div>
)
}

Glass (opt-in)

variant="glass" is opt-in. It blurs and tints what sits behind the panel (with a readable opacity floor), so it needs a colourful or photographic backdrop: switch the stage backdrop to see it.

import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from "@glinui/ui"
export function Demo() {
return (
<HoverCard>
<HoverCardTrigger asChild><Button variant="outline">Hover for glass</Button></HoverCardTrigger>
<HoverCardContent variant="glass">Frosted, with a readable floor.</HoverCardContent>
</HoverCard>
)
}

Delays and Surfaces

import { Badge, HoverCard, HoverCardContent, HoverCardTrigger } from "@glinui/ui"

export function HoverCardDelayDemo() {
  return (
    <div className="flex flex-wrap items-center gap-4">
      <HoverCard openDelay={0} closeDelay={150}>
        <HoverCardTrigger asChild>
          <button className="text-sm font-medium underline decoration-dotted underline-offset-4">
            Instant preview
          </button>
        </HoverCardTrigger>
        <HoverCardContent variant="glass" size="sm">
          <div className="space-y-2">
            <Badge variant="glass">glass</Badge>
            <p className="text-xs text-neutral-600 dark:text-neutral-300">Open delay: 0ms</p>
          </div>
        </HoverCardContent>
      </HoverCard>
      <HoverCard openDelay={500} closeDelay={250}>
        <HoverCardTrigger asChild>
          <button className="text-sm font-medium underline decoration-dotted underline-offset-4">
            Delayed preview
          </button>
        </HoverCardTrigger>
        <HoverCardContent variant="outline" size="md">
          <p className="text-xs text-neutral-600 dark:text-neutral-300">
            Opens after 500ms with outline surface.
          </p>
        </HoverCardContent>
      </HoverCard>
    </div>
  )
}

Accessibility

  • Built on Radix Hover Card and opens on hover and keyboard focus.
  • Hover card content should be supplemental; avoid critical-only information.
  • Use non-interactive preview content for concise summaries.
  • Use concise supplemental content, not primary actions.
  • Keep the trigger semantic and focusable (`button`, `a`, etc.).
  • For interactive panels, prefer `Popover`.

Keyboard Interactions

KeyAction
Tab / Shift+TabMove focus to or away from the trigger.
EscapeClose the hover card when focused.

ARIA Attributes

  • `aria-describedby` linkage is handled by Radix primitives
  • Trigger remains semantic and keyboard reachable

Reduced Motion

Entrance and exit transitions are disabled under `prefers-reduced-motion`.

Affected properties

opacitytransform

API Reference

HoverCardProps

PropTypeRequiredDefaultDescription
openDelaynumberNo200Delay in milliseconds before opening on hover/focus.
closeDelaynumberNo100Delay in milliseconds before closing after pointer leaves.
openboolean--Controlled open state.
defaultOpenboolean--Initial open state for uncontrolled usage.
onOpenChange(open: boolean) => void--Open state change handler.

HoverCardContentProps

PropTypeRequiredDefaultDescription
variantPanelVariantPropNoambient style (glinr)Panel look. Omit it for the ambient design style (glinr shell with a gradient hairline ring). `plain` is the shadcn border and shadow, `glass` is opt-in and needs a backdrop.
size"sm" | "md" | "lg"NomdContent width and density scale.
align"start" | "center" | "end"-centerAlignment relative to the trigger.
side"top" | "right" | "bottom" | "left"NobottomPreferred side for content placement.
sideOffsetnumberNo10Distance from trigger in pixels.
containerHTMLElement | nullNo-Element to portal into. Defaults to document.body.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { HoverCard } from "@glinui/ui"

Source Files

Dependencies

@glinui/ui

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/hover-card.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

HoverCardProps

HoverCardContentProps

PropTypeRequiredDefaultDescription
containerHTMLElement | nullNo-Element to portal into. Defaults to document.body.
side"top" | "right" | "bottom" | "left"No-Preferred side for the hover card.
sideOffsetnumberNo10Gap in px between trigger and content.
size"sm" | "md" | "lg"No"md"Variant option from hoverCardContentVariants.
variantPanelVariantPropNo-Surface look. Omit for the ambient design style (glinr by default). `glass` is opt-in and needs a rich backdrop.

HoverCardProps

PropTypeRequiredDefaultDescription
closeDelaynumberNo100Delay in ms before closing when pointer leaves.
openDelaynumberNo200Delay in ms before opening on pointer/focus.