# Astryx Popover vs HoverCard vs Tooltip: Interaction Patterns Explained

> Compare Astryx Popover, HoverCard, and Tooltip. Understand their distinct interaction patterns, timing, and UX purposes for effective UI design.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: deep-dive
- Published: 2026-08-04

---

**The Astryx `Tooltip` and `HoverCard` components are both hover-triggered overlays built on the same low-level `Popover` API, but they differ in interactivity, timing, and UX purpose: Tooltips show brief, non-interactive hints with a default 200ms delay, while HoverCards display rich, interactive content immediately and stay open during user interaction.**

Astryx provides three related but distinct primitives for contextual overlays in the `@astryxdesign/core` library. Understanding the interaction patterns of **Popover**, **HoverCard**, and **Tooltip** components ensures you select the right tool for your interface—whether you need a lightweight hint, an interactive preview, or a fully controlled overlay.

## The Foundation: Shared Popover API

All three components rely on the same underlying **Popover** architecture for positioning and rendering. In [`packages/core/src/Popover/Popover.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Popover/Popover.tsx), the core API handles CSS-anchor positioning, portal management, and layer stacking through [`packages/core/src/Layer/useLayer.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layer/useLayer.tsx). This shared foundation guarantees consistent performance and accessibility across the ecosystem.

The **Popover** serves as the low-level primitive. **Tooltip** and **HoverCard** wrap this primitive with specialized hooks—`useTooltip` and `useHoverCard`—that implement distinct interaction patterns for different use cases.

## Tooltip: Lightweight, Non-Interactive Hints

The **Tooltip** component in [`packages/core/src/Tooltip/Tooltip.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Tooltip/Tooltip.tsx) is designed for concise, informational text that requires no user action.

### Trigger and Timing Behavior

- **Delay**: Opens after **200ms hover delay** by default (configurable)
- **Dismiss**: Closes immediately when cursor leaves (or after optional `hideDelay`)
- **Focus support**: Appears on keyboard focus for accessibility

### Content and ARIA Pattern

Tooltip content is **plain text only**—no buttons, links, or inputs. The trigger receives `aria-describedby` pointing to the tooltip text, creating an accessible description relationship without focus management complexity.

```tsx
import {Tooltip} from '@astryxdesign/core/Tooltip';
import {Button} from '@astryxdesign/core/Button';

<Tooltip content="Save your changes" placement="above">
  <Button>Save</Button>
</Tooltip>

```

### Visual Treatment

Tooltips render with a dark background and light text. An optional **hover indication** (dashed underline) can appear on the trigger element to signal that additional information is available.

## HoverCard: Rich, Interactive Previews

The **HoverCard** component in [`packages/core/src/HoverCard/HoverCard.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/HoverCard/HoverCard.tsx) supports complex, interactive content that users may want to engage with.

### Trigger and Timing Behavior

- **No default delay**: Opens **immediately** on hover or focus
- **Persistent state**: Stays open while cursor hovers **either the trigger or the card itself**
- **Safe area**: Includes buffer zones to prevent accidental dismissal during traversal

### Content and ARIA Pattern

HoverCards can contain **any interactive elements**—buttons, links, avatars, forms. The component manages **focus trapping** and **keyboard navigation** while open. It also uses `aria-describedby`, but the described element is an interactive layer that may itself receive focus.

```tsx
import {HoverCard} from '@astryxdesign/core/HoverCard';
import {Avatar} from '@astryxdesign/core/Avatar';
import {Button} from '@astryxdesign/core/Button';

<HoverCard
  content={
    <div style={{padding: 12}}>
      <Avatar src="/me.jpg" size="large" />
      <p>Jane Doe – Product Designer</p>
      <Button>Message</Button>
    </div>
  }
  placement="below"
>
  <span style={{textDecoration: 'underline'}}>Jane</span>
</HoverCard>

```

### Visual Treatment

HoverCards have **customizable styling** with no built-in hover indication—the card's visual presence alone provides affordance. This flexibility supports profile previews, mini-menus, and rich media cards.

## Key Implementation Differences

| Aspect | Tooltip | HoverCard |
|--------|---------|-----------|
| **Hook location** | [`packages/core/src/Tooltip/useTooltip.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Tooltip/useTooltip.tsx) | [`packages/core/src/HoverCard/useHoverCard.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/HoverCard/useHoverCard.tsx) |
| **Default delay** | 200ms | 0ms (none) |
| **Dismiss behavior** | On cursor exit | On cursor exit from both trigger and card |
| **Interactive content** | Not supported | Fully supported |
| **Focus management** | Minimal (describedby only) | Full navigation handling |
| **Typical use** | Inline help, icon labels | Profile cards, quick actions |

## When to Use Each Component

Choose based on content interactivity and user intent:

- **Tooltip**: Use for **brief explanations** of UI elements—button purposes, icon meanings, validation hints. Keep text under 60 characters.

- **HoverCard**: Use for **rich previews** that merit user investment—profile cards with contact actions, definition popups with related links, or tool palette summaries.

- **Popover (direct)**: Use when you need **manual control** over open/close state, click triggers, or complex positioning logic that the higher-level abstractions don't support.

## Summary

- **Tooltip** and **HoverCard** both extend the core **Popover** API with specialized interaction patterns
- **Tooltip** prioritizes speed and simplicity: delayed opening, quick dismissal, non-interactive content
- **HoverCard** prioritizes engagement: immediate opening, persistent state during interaction, full content flexibility
- Both share positioning infrastructure via `useLayer` in [`packages/core/src/Layer/useLayer.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Layer/useLayer.tsx)
- Select components based on whether users need to **read** (Tooltip) or **interact** (HoverCard)

## Frequently Asked Questions

### Does HoverCard support the same delay configuration as Tooltip?

Yes, but the defaults differ. The `useHoverCard` hook accepts delay parameters, though it defaults to 0ms. The `useTooltip` hook in [`packages/core/src/Tooltip/useTooltip.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Tooltip/useTooltip.tsx) explicitly sets 200ms as the default. You can override either behavior through props to match your specific UX requirements.

### Can I put a button inside a Tooltip?

No. Tooltips are engineered for **non-interactive content only**. Attempting to include focusable elements violates the Astryx component contract and produces accessibility warnings. For interactive content, use **HoverCard** or the base **Popover** component with manual state control.

### Do both components work with keyboard navigation?

Yes, but differently. Tooltips appear on focus and dismiss on blur without trapping focus. HoverCards implement **focus management**—when opened via keyboard, focus moves into the card and `Tab` / `Shift+Tab` cycle through interactive elements. The `useHoverCard` hook handles this automatically.

### Which component should I use for a definition popup with a "Read more" link?

Use **HoverCard**. The presence of a **clickable link** makes this interactive content unsuitable for Tooltip. The HoverCard's persistent hover state lets users traverse from trigger to card without dismissal, and its focus management supports keyboard activation of the link.