HoverCard
hover-cardShows rich content after pointer hover and closes it after a leave delay.
Usage
Basic usage
The information card is delayed when hovering the link/entry, and is closed when moved out; it is non-modal, does not lock the scroll, and does not grab the focus.
tsx
<HoverCard>
<HoverCardTrigger render={<button type="button">@HulianDesignSystem</button>} />
<HoverCardContent>
<div className="flex gap-3">
<div className="size-10 rounded-full bg-primary/12">hu</div>
<div>
<p>Hulian Design System</p>
<p> Absorb the best implementations from various companies and unify them into a set of Hulian API + light and dark token. </p>
</div>
</div>
</HoverCardContent>
</HoverCard>Pop-up direction
side controls the orientation of the card relative to the trigger, and the arrow automatically continues on the corresponding edge.
tsx
<>
<HoverCard>
<HoverCardTrigger render={<button type="button">Expand upward</button>} />
<HoverCardContent side="top">{/* Avatar + Introduction */}</HoverCardContent>
</HoverCard>
<HoverCard>
<HoverCardTrigger render={<button type="button">Expand right</button>} />
<HoverCardContent side="right">{/* Avatar + Introduction */}</HoverCardContent>
</HoverCard>
</>When to use
Use HoverCard for rich content revealed on hover, such as a profile card, term definition, or link preview. Open and close delays reduce accidental activation. Use Tooltip for short plain text, Popover for click-triggered actions, or Glimpse for a standard cover/title/domain link preview.
Import
ts
import { HoverCard, HoverCardTrigger, HoverCardContent } from "@hulianui/ui"Props
HoverCard:
| Name | Type | Default | Description |
|---|---|---|---|
| openDelay | number | 300 | Hover duration in milliseconds before opening. |
| closeDelay | number | 150 | Delay in milliseconds before closing after pointer exit. |
HoverCardContent:
| Name | Type | Default | Description |
|---|---|---|---|
| side | "top"|"right"|"bottom"|"left" | "bottom" | Preferred popup side. |
| align | "start"|"center"|"end" | "center" | Alignment along the trigger. |
| sideOffset | number | 8 | Distance from the trigger in pixels. |
| anchor | Element|RefObject<Element>|VirtualElement|(() => Element|VirtualElement|null) | - | Position the card against something other than the trigger, with the same contract as Popover's anchor. One difference: the trigger stays mandatory, because the card opens on hover, so anchor only changes where it sits, not what opens it. |
| className | string | - | Additional class name. |
Slots
| Slot | Type | Description |
|---|---|---|
HoverCard children | ReactNode | Trigger and Content composition. |
HoverCardContent children | ReactNode | Rich card content. |
Use render on HoverCardTrigger to supply an inline link or button.
Example
tsx
<HoverCard>
<HoverCardTrigger render={<button type="button" className="font-medium text-primary underline">@Hulian design system</button>} />
<HoverCardContent side="bottom" align="center">
<div className="flex gap-3">
<div className="flex size-10 items-center justify-center rounded-full bg-primary/12 text-primary">H</div>
<div className="space-y-1">
<p className="text-sm font-semibold text-foreground">Hulian design system</p>
<p className="text-xs text-muted-foreground">Opens on hover · closes after a delay</p>
</div>
</div>
</HoverCardContent>
</HoverCard>Usage guidelines
- The component disables managed initial and final focus as described in [[hovercard-on-focus-managing-popover-flickers-set-initial-final-focus-false]]. This prevents hover and focus from repeatedly opening and closing a focus-managing popover. Preserve that behavior in forks.
- Tune accidental activation with
openDelayandcloseDelay. A zero close delay can flash closed while the pointer crosses the gap from trigger to card. HoverCardContentextends the native div attributes, sodata-testid,role,aria-*, andonClickall attach directly. The card is portaled out, but synthetic events still bubble along the React tree back to the parent that holds the trigger. Inside a fully clickable row or card, addonClick={(e) => e.stopPropagation()}or clicking the card content also fires the rowonClick. A forwardedonMouseEnteroronMouseLeaveis merged with the internal timers rather than replacing them, so it cannot accidentally close the card.
Related
Playground
<HoverCard>
<HoverCardTrigger render={<a>@Hulian</a>} />
<HoverCardContent side="bottom" align="center">
{/* Avatar + Introduction */}
</HoverCardContent>
</HoverCard>