Skip to main content

HoverCard

HoverCard is a floating content container that appears when a user hovers over or focuses on a trigger element. It is useful for previews, tooltips with rich content, user cards, and contextual details.


Usage

Basic usage

import { HoverCard } from '@nofinite/nui';

<HoverCard>
<HoverCard.Trigger>
<button>User</button>
</HoverCard.Trigger>

<HoverCard.Content>User preview</HoverCard.Content>
</HoverCard>;

Top placement

<HoverCard>
<HoverCard.Trigger>
<button>Hover</button>
</HoverCard.Trigger>

<HoverCard.Content placement="top">Top card</HoverCard.Content>
</HoverCard>

Custom delays

<HoverCard openDelay={400} closeDelay={200}>
<HoverCard.Trigger>
<button>Hover</button>
</HoverCard.Trigger>

<HoverCard.Content>Delayed card</HoverCard.Content>
</HoverCard>

Props

Root

PropTypeDefaultDescription
childrenReactNodeCompound structure
openDelaynumber200Hover open delay (ms)
closeDelaynumber300Hover close delay (ms)

Content

PropTypeDefaultDescription
placement'top' | 'bottom'bottomPreferred vertical placement
offsetnumber8Distance from trigger
classNamestringStyle override
childrenReactNodeContent body

Extends React.HTMLAttributes<HTMLDivElement>.


Subcomponents

  • HoverCard.Trigger
  • HoverCard.Content

Variants

<HoverCard />
<HoverCard openDelay={400} />
<HoverCard closeDelay={100} />
<HoverCard.Content placement="top" />
<HoverCard.Content placement="bottom" />

Available variants:

  • default-delay
  • custom-delay
  • top
  • bottom
  • auto-flip

Guidelines:

  • Use hovercard for previews or metadata
  • Avoid embedding critical actions
  • Maintain short dwell open delays

Sizes

ElementBehavior
Contentmin 240px / max 360px
Paddingtoken-based spacing
Widthintrinsic with clamp

Sizing should be customized via tokens or class overrides.


Shapes / Modes

Interaction states

  • Closed
  • Scheduled-open
  • Visible
  • Scheduled-close
  • Hover-persistent
  • Escape-dismissed
  • Outside-click dismissed

Placement states

  • Bottom
  • Top
  • Collision-flipped

Design tokens / theming

Uses NUI tokens:

  • --nui-bg-surface
  • --nui-fg-default
  • --nui-border-default
  • --nui-radius-lg
  • --nui-space-4
  • --nui-font-sans
  • --nui-z-dropdown

Shadow uses soft dual-layer elevation.


Accessibility

Implemented:

  • Trigger
    • aria-haspopup="dialog"
    • aria-expanded
    • aria-controls
    • focus-triggered open
  • Content
    • role="dialog"
    • ESC dismiss
    • click-outside dismiss
  • Hover persistence prevents premature close
  • Portal avoids stacking context clipping

Limitations:

  • No focus trap (intentional for hover semantics)
  • No aria-live announcements
  • Screen reader discovery relies on focus
  • Keyboard navigation inside card not enforced

Animation model

  • Entry animation: scale + translate + fade
  • Duration: 150ms cubic-bezier easing
  • Placement-aware transform origin
  • Motion disabled via prefers-reduced-motion

No exit animation (timer-based unmount).


Architectural notes

Key behaviors:

  • Timer orchestration prevents hover jitter
  • Portal rendering solves overflow clipping
  • Collision-aware vertical flipping
  • Horizontal clamp with viewport padding
  • Scroll + resize reactive positioning
  • Hover-safe bridging between trigger and card
  • Layout-safe positioning via useLayoutEffect
  • Compound component architecture with shared context

Potential caveat:

  • Position recalculation may be expensive under heavy scroll containers

Best practices

Do

  • Use for previews, metadata, secondary info
  • Keep content lightweight
  • Maintain open delay to avoid accidental triggers
  • Provide keyboard focusable content if interactive

Don’t

  • Use as replacement for tooltip or modal
  • Put destructive actions inside
  • Depend on hovercard for critical information
  • Render large trees inside portal