Noctis

Tooltip

A hint bubble that reveals supplementary text on hover and on keyboard focus. Decoupled from any particular trigger — attach it to whatever control you pass. It paints the engine-derived overlay surface shared with the menu and popover, sits flush against its anchor, and dismisses on Escape.

Basic

A Tooltip.Trigger reveals the Tooltip.Popup after a short delay on hover, and immediately on keyboard focus. Compose the trigger from a Button via render so it keeps the button's look, hover, and focus.

Use a tooltip to explain why something exists or how it behaves — not to restate a label that's already visible. It is supplementary by design, so the information it carries must also live somewhere a touch user and a screen reader can reach.

Naming an icon-only control

A tooltip's most common job is to name an icon-only button. Give the control an aria-label (the accessible name screen readers announce), and let the tooltip carry the same label as a visible hint for sighted pointer and keyboard users.

Shortcut hints

Pair a label with its keyboard shortcut so every hover doubles as a reminder of the binding. Compose Kbd inside the popup; it sits on the same overlay surface as a menu, so a ⌘S reads identically in either place. Keep the binding itself live on the control (aria-keyshortcuts) — the tooltip is the visible echo, not the wiring.

Rich text

A hint can run to a sentence or two and hold inline InlineCode. The bubble fills to a sensible max width before wrapping. Keep it to text and inline marks — a tooltip never holds a focusable or interactive element; reach for a Popover when the content needs a link, a button, or its own focus.

Positioning

The bubble opens above the trigger, centered, by default. Steer it with side and align (and sideOffset / alignOffset) on Tooltip.Popup — alignment is direction-aware, so inline-start/inline-end flip under RTL. The bubble flips to the opposite side to avoid a viewport collision, and collisionPadding (default 8) keeps it off the edges.

Arrow

Noctis tooltips sit flush by default — a caret only adds noise most of the time. Where a pointer back to the trigger genuinely helps (a cursor-tracked or free-floating hint), compose Tooltip.Arrow inside the popup. It reads the bubble's own surface fill and border and mirrors automatically per side, RTL included; pair it with a slightly larger sideOffset so the tip meets the trigger.

Shared delay

Wrap a cluster of tooltips in a Tooltip.Provider to share one open delay. This is the warmup/cooldown grace window: the first hint waits out the delay, then while any tooltip in the group stays open — and for a short cooldown (timeout) after the last one closes — the next opens instantly. Scrubbing across a toolbar feels immediate after the first hint, without each control waiting out its own delay.

Keyboard

KeyAction
TabMove focus to the trigger — the tooltip opens immediately (no hover delay).
EscClose the tooltip while keeping focus on the trigger.

Moving focus away from the trigger (a further Tab, or a click elsewhere) closes the tooltip. A tooltip is supplementary by design: it never traps focus and holds nothing interactive, so it can't be the only place a piece of information or an action lives.

Disabled triggers and touch

Two cases need care, both because the tooltip never gets its open signal:

  • Disabled controls don't fire pointer or focus events, so a tooltip attached directly to one never opens — which is a shame, since explaining why a control is disabled is one of the most useful things a tooltip does. Attach the trigger to a focusable wrapper <span tabIndex={0}> and drop the control's pointer events, so the span catches the hover and keyboard focus while the button still reads as disabled.
  • Touch has no hover and no persistent focus, so tooltips effectively don't show. Never let a tooltip be the only place information or an action lives; route anything touch-critical to visible text or a Popover.

Anatomy

Compose a tooltip from its parts. Tooltip.Root owns the open state (it accepts every Base UI Tooltip.Root prop — open, defaultOpen, onOpenChange, disabled, trackCursorAxis).

  • Tooltip.Provider — shares one open/close delay across a group of tooltips; mount it once high in the tree. Optional.
  • Tooltip.Root — owns the open state; renders no element of its own. disableHoverablePopup defaults to true for the plain bubble.
  • Tooltip.Trigger — the anchored control. Style it directly or compose another control through render. The hover delay defaults to 300ms.
  • Tooltip.Popup — the floating, animated bubble holding the hint. Props: side (default top), align (default center), sideOffset (default 6), alignOffset, collisionPadding (default 8), arrowPadding, collisionBoundary, sticky.
  • Tooltip.Arrow — an opt-in caret composed inside the popup; absent by default (the bubble is flush).

Every rendered part carries a data-slot (tooltip-trigger, tooltip-popup, tooltip-arrow) for host-side styling. The resolved-position attributes (data-side, data-align) land on both the internal positioner and the popup; pair a slot with the Base UI state attributes (data-open, data-closed, data-instant) to target a part mid-transition.

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every tooltip in that region retunes — e.g. .dense { --noctis-tooltip-popup-max-inline-size: 14rem; } narrows every bubble opened beneath it. The bubble's fill, border, and shadow come from the composed Surface (the engine-derived overlay surface), not a minted token. See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table; parts that only forward to Base UI list just the props they pass through.

Tooltip.Provider

No props of its own — forwards to the underlying Base UI part.

Tooltip.Root

No props of its own — forwards to the underlying Base UI part.

Tooltip.Trigger

Prop

Tooltip.Popup

Prop

Tooltip.Arrow

Prop

AttributeDescription
data-slotThe trigger element the tooltip is attached to.
data-openPresent on the popup while the tooltip is open.
data-closedPresent on the popup while the tooltip is closed (before it unmounts).
data-sideThe side of the trigger the popup actually rendered on (`top`, `bottom`, `inline-start`, …).
data-alignHow the popup is aligned along that side (`start`, `center`, `end`).
data-starting-stylePresent on the popup for the first frame after mount — the transition's start state.
data-ending-stylePresent on the popup while it transitions out before unmounting.
data-instantPresent on the popup when the change should not animate (focus open, dismissal).