Skip to main content

Tooltip

A fully accessible tooltip component that displays contextual information on hover, focus, or keyboard interaction without mutating or cloning its child.


Usage

Basic usage

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

<Tooltip label="This deletes the item permanently">
<button>Delete</button>
</Tooltip>;

With custom styling

<Tooltip label="This action cannot be undone" className="danger-tooltip">
<span>Hover me</span>
</Tooltip>

Variants

Tooltip does not expose visual variants by default. Styling and theming are controlled via CSS variables and the optional className prop.

Guidelines:

  • Use design tokens (--color-bg-secondary, --color-text, etc.) for consistent theming.
  • Prefer semantic meaning in tooltip text rather than long explanations.

Sizes

The tooltip does not have explicit size variants.

  • Size adapts automatically to its content.
  • Padding, font-size, and border-radius are controlled via CSS.
  • Size can be customized using className if needed.

States

The tooltip manages its own internal visibility state.

// Visible when hovered, focused, or triggered via keyboard
<Tooltip label="Info">
<button>Action</button>
</Tooltip>

Behavior:

  • Appears on hover and focus.
  • Hides on mouse leave, blur, or Escape key.
  • Non-interactive (pointer-events: none) to avoid focus traps.

Native Props / Composition

Tooltip does not clone or mutate its child.

  • Children are safely wrapped in a <span> trigger.
  • Any valid React node is supported (button, icon, text, custom component).
<Tooltip label="More information" className="custom-tooltip">
<IconInfo />
</Tooltip>

Props

PropTypeDefaultDescription
labelstringText content shown inside the tooltip bubble
childrenReact.ReactNodeElement that triggers the tooltip
classNamestring""Additional class names applied to the tooltip bubble

Behavior Notes

  • Uses a portal-based bubble, rendered outside normal DOM flow.
  • Automatically positions itself above the trigger element.
  • Calculates position using getBoundingClientRect.
  • Listens for Escape key globally when visible.
  • Safe for strict mode and server components (client usage required).

Example:

<Tooltip label="Keyboard accessible">
<button>Focus me</button>
</Tooltip>

Accessibility

  • Renders tooltip content with role="tooltip".

  • Uses aria-describedby on the trigger when visible.

  • Fully keyboard accessible:

    • Tab to focus
    • Escape to dismiss
  • Does not interfere with child semantics or refs.

Example:

<Tooltip label="Close panel">
<button aria-label="Close">×</button>
</Tooltip>

Layout

  • Trigger wrapper uses inline-flex.
  • Tooltip bubble is position: fixed and rendered via a portal.
  • Does not affect layout or surrounding elements.
<Tooltip label="Full-width parent safe">
<div style={{ width: '100%' }}>Hover area</div>
</Tooltip>

Best Practices

Do

  • Use for short, contextual hints.
  • Keep tooltip text concise and descriptive.
  • Use with icons or destructive actions for clarity.

Don’t

  • Put long paragraphs or complex interactions inside tooltips.
  • Use as a replacement for visible labels or instructions.
  • Nest interactive elements inside tooltip content.