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
classNameif 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
Escapekey. - 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
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Text content shown inside the tooltip bubble |
children | React.ReactNode | — | Element that triggers the tooltip |
className | string | "" | 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
Escapekey 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-describedbyon the trigger when visible. -
Fully keyboard accessible:
Tabto focusEscapeto 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: fixedand 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.