useTooltip
Hook that manages tooltip open state, hover/focus triggers, delay timing, and group transitions.
Usage#
import { usePositioner } from '@primereact/headless/positioner';
import { useTooltip } from '@primereact/headless/tooltip';
import { useTooltipManager } from '@primereact/headless/tooltipmanager';
import { createPortal } from 'react-dom';const manager = useTooltipManager();
const { triggerProps, popupProps, arrowProps, positionerProps, setAnchorRef, setPositionerRef, setArrowRef, state, presence } = useTooltip({ tooltipManager: manager });
usePositioner({
anchor: state.anchorElement,
content: state.positionerElement,
arrow: state.arrowElement,
side: 'top',
sideOffset: 8,
flip: true
});useTooltip manages hover/focus open behavior with configurable delays. Use useTooltipManager to coordinate instant transitions between adjacent tooltips in a group. See Primitive for a component-based API.
Features#
- Hover/focus open — opens on pointer enter or keyboard focus, closes on leave/blur with configurable
openDelayandcloseDelay - Presence tracking —
presence.presentandpresence.refkeep the popup mounted through exit animations - Interactive hover — allows the pointer to enter the popup without dismissing, configurable via the
interactiveprop - Group coordination —
useTooltipManagerskips the open delay when moving between adjacent tooltips for an "instant" transition - Transition awareness —
state.instantTypereports the current mode ('delay','focus','dismiss', orundefined) for styling - Ref callbacks —
setAnchorRef,setPositionerRef, andsetArrowRefregister elements for positioning without manual ref merging
Working with callbacks#
Controlled open state#
Pass open and onOpenChange to drive visibility from external state — useful when pairing with custom triggers or analytics.
const [isOpen, setIsOpen] = React.useState(false);
const tooltip = useTooltip({
open: isOpen,
onOpenChange: (e) => setIsOpen(e.open)
});
<>
<button {...triggerProps} ref={setAnchorRef}></button>;
{
presence.present &&
createPortal(
<div {...positionerProps} ref={setPositionerRef}>
<div {...popupProps} ref={presence.ref}>
<div {...arrowProps} ref={setArrowRef} />
</div>
</div>,
document.bodyTuning open and close delays#
Adjust openDelay and closeDelay to match the UI feel. Shorter delays feel snappier; longer delays avoid accidental opens.
const tooltip = useTooltip({ openDelay: 300, closeDelay: 200 });Group transitions with a manager#
Share a useTooltipManager instance so moving the pointer between siblings skips the open delay.
const manager = useTooltipManager({ timeout: 400 });
const tooltip1 = useTooltip({ tooltipManager: manager });
const tooltip2 = useTooltip({ tooltipManager: manager });Non-interactive tooltip#
Set interactive to false when the popup should dismiss immediately on pointer leave, even if the user moves over the tooltip content.
const tooltip = useTooltip({ interactive: false });Composing with usePositioner#
Register the element refs with the positioner so the tooltip flips and offsets against the trigger.
const { state, setAnchorRef, setPositionerRef, setArrowRef } = useTooltip();
usePositioner({
anchor: state.anchorElement,
content: state.positionerElement,
arrow: state.arrowElement,
side: 'top',
sideOffset: 8,
flip: true
});Styling with data attributes#
The hook exposes state through data-* attributes on each part. Use them as CSS selectors — no className juggling.
| Scope | Part | States |
|---|---|---|
tooltip | trigger | data-popup-open |
tooltip | popup | data-open, data-closed, data-instant |
[data-scope='tooltip'][data-part='popup'][data-open] {
opacity: 1;
scale: 1;
}
[data-scope='tooltip'][data-part='popup'][data-instant] {
transition-duration: 0s;
}
[data-scope='tooltip'][data-part='trigger'][data-popup-open] {
background-color: light-dark(var(--p-surface-100), var(--p-surface-700));
}API#
useTooltip#
| Name | Type | Default |
|---|---|---|
anchor | HTMLElement | undefined |
| External anchor element for positioning the tooltip programmatically. When provided, it is used instead of the element attached via `Tooltip.Trigger` . | ||
open | boolean | — |
| Controls the open state of the tooltip. | ||
defaultOpen | boolean | false |
| Whether the tooltip is open by default. | ||
onOpenChange | (event: useTooltipChangeEvent) => void | undefined |
| Callback fired when the open state changes. | ||
onExitComplete | () => void | undefined |
| Callback fired after the leave (exit) transition completes. | ||
disabled | boolean | false |
| Whether the tooltip is disabled. | ||
openDelay | number | 600 |
| The delay in milliseconds before opening the tooltip on hover. | ||
closeDelay | number | 0 |
| The delay in milliseconds before closing the tooltip. | ||
interactive | boolean | true |
| Whether the tooltip popup is interactive (hoverable). When true, hovering over the popup keeps the tooltip open. When false, the tooltip closes as soon as the pointer leaves the trigger. | ||
tooltipManager | useTooltipManagerExposes | — |
| The tooltip manager instance for group behavior. | ||
useTooltipManager#
| Name | Type | Default |
|---|---|---|
openDelay | number | — |
| The delay in milliseconds before opening a tooltip. | ||
closeDelay | number | — |
| The delay in milliseconds before closing a tooltip. | ||
timeout | number | 400 |
| The timeout in milliseconds for the instant phase. If another tooltip opens within this timeout after a tooltip closes, the transition will be instant. | ||
Accessibility#
Focus or hover shows the tooltip, Escape hides it, and content is announced via aria-describedby. See Primitive for full WAI-ARIA compliance details.