Tooltip
elements man ui/templates/tooltipA short label for a control, shown on hover and keyboard focus.
Exampleimport { Tooltip, TooltipProvider, TooltipTrigger } from "@elements/ui/tooltip"; import { Button } from "@elements/ui/button"; import { Icon } from "@elements/ui/icon"; <Tooltip content="Add to library"> <Button slot="trigger" icon label="Add"><Icon name="plus" /></Button> </Tooltip> <!-- one delay for a region; the next tooltip opens at once --> <TooltipProvider delay={300}>...</TooltipProvider>
Parts
| Part | What it is |
|---|---|
TooltipProvider |
Optional. Sets delay, skipDelay, closeDelay and disableHoverableContent for every tooltip inside it. |
Tooltip |
The root: owns open, renders the trigger slot and, while open, the role=tooltip content. |
TooltipTrigger |
Wraps a trigger anywhere on the page for the Tooltip with the same handle. Takes handle and payload. |
Attributes
Tooltip
| Attribute | Type | Default | Description |
|---|---|---|---|
open |
boolean (two-way) |
false |
Whether the tooltip is open. Bind it to control it; it writes false back when it closes itself. |
content |
string |
"" |
The tooltip's text. For rich content, use the default slot. |
label |
string |
"" |
What a screen reader reads instead of the visible content (aria-label on the tooltip). |
side |
"top" | "right" | "bottom" | "left" | "inline-start" | "inline-end" |
"top" |
Preferred side; it flips when there is no room. inline-start and inline-end follow the text direction (right and left under dir=rtl). |
align |
"start" | "center" | "end" |
"center" |
Alignment along that side. |
sideOffset |
number | ((d: OffsetData) => number) |
4 |
Gap from the trigger, in px. |
alignOffset |
number | ((d: OffsetData) => number) |
0 |
Shift along the alignment axis, in px. |
avoidCollisions |
boolean |
true |
Flip and shift to stay on screen. |
collisionAvoidance |
{ side?: "flip" | "shift" | "none"; align?: "flip" | "shift" | "none"; fallbackAxisSide?: "start" | "end" | "none" } | null |
null |
How it stays in view. side "none" keeps the side with no flip, "shift" keeps the side and slides it over the trigger into view; align "flip" tries the other alignment before sliding, "shift" only slides, "none" neither; fallbackAxisSide "start" tries the inline start side of the other axis first, "end" (the default) the end side, "none" never moves it to the other axis. avoidCollisions={false} turns all of it off. |
positionMethod |
"fixed" | "absolute" |
"fixed" |
"absolute" places the tooltip in page coordinates instead of viewport ones. |
collisionPadding |
number |
8 |
Distance kept from the viewport edge, in px. |
collisionBoundary |
string | Element | Element[] |
"" |
A selector or elements whose edges flip and shift keep it inside, besides the viewport. |
arrowPadding |
number |
6 |
Distance the arrow keeps from the corners, in px. |
sticky |
"partial" | "always" |
"partial" |
"always" keeps it in the collision boundary after its anchor scrolls away. |
hideWhenDetached |
boolean |
false |
Hide while the trigger is scrolled out of view. |
anchor |
string |
"" |
CSS selector of an element to position against instead of the trigger. |
keepMounted |
boolean |
false |
Keep the closed tooltip in the page, hidden, rather than removing it. |
disableAnchorTracking |
boolean |
false |
Place it once when it opens; it stays put while the page scrolls, and is placed again on a window resize. |
handle |
string |
"" |
Names it for TooltipTrigger parts elsewhere on the page. |
triggerId |
string (two-way) |
"" |
The id of the active trigger's element. Set it with open to open against that trigger. |
payload |
string (two-way) |
"" |
The payload of the TooltipTrigger it is showing for, for the content to read. |
arrow |
boolean |
true |
Draw an arrow pointing at the trigger. |
delay |
number |
-1 |
ms the pointer rests before it opens. -1 uses the TooltipProvider's delay, else 700. |
closeDelay |
number |
-1 |
ms before it closes after the pointer leaves. -1 uses the TooltipProvider's closeDelay, else 0. |
disableHoverableContent |
boolean |
false |
Close as soon as the pointer leaves the trigger, even toward the tooltip. |
closeOnClick |
boolean |
true |
A press on the trigger closes it. |
disabled |
boolean |
false |
Never open. |
trackCursorAxis |
"none" | "x" | "y" | "both" |
"none" |
Follow the pointer along this axis while it moves over the trigger. |
class |
string |
"" |
Extra classes on the tooltip. |
onOpenChange |
(open: boolean, details: OpenChangeDetails) => void |
() => {} |
Called when the tooltip opens or closes itself, before the change. details.reason says why (trigger-press, trigger-hover, escape-key, outside-press, close-press, focus-out); details.trigger is the trigger element that caused it (undefined when no trigger did); details.cancel() keeps the current state. Not called for changes the caller makes. |
onOpenChangeComplete |
(open: boolean) => void |
() => {} |
Called after the enter or exit animation finishes. |
onEscapeKeyDown |
(e: KeyboardEvent) => void |
() => {} |
Called on Escape; e.preventDefault() keeps it open. |
onPointerDownOutside |
(e: PointerEvent) => void |
() => {} |
Called on a press outside; e.preventDefault() keeps it open. |
TooltipTrigger
| Attribute | Type | Default | Description |
|---|---|---|---|
handle |
string |
(required) | The handle it is a trigger for. |
payload |
string |
"" |
Data handed to payload while this trigger is active. |
TooltipProvider
| Attribute | Type | Default | Description |
|---|---|---|---|
delay |
number |
700 |
Open delay for the tooltips inside. |
skipDelay |
number |
300 |
Within this many ms of a tooltip closing, the next opens at once. |
closeDelay |
number |
0 |
Close delay for the tooltips inside. |
disableHoverableContent |
boolean |
false |
The same, for every tooltip inside. |
Slots
| Slot | Part | Content |
|---|---|---|
trigger |
The described element. It gets data-state, and aria-describedby pointing at the tooltip while open. Wrap a disabled button in a focusable span. | |
default |
Rich content, after the content attribute's text. | |
default |
TooltipProvider |
The region whose tooltips share its settings. |
Keyboard
| Keys | Action |
|---|---|
Tab |
Focusing the trigger opens the tooltip at once; moving focus away closes it. |
Space / Enter |
Closes the tooltip; the trigger's own action still runs. |
Escape |
Closes the tooltip. Focus stays on the trigger. |
Data attributes
| Attribute | Values | On | Description |
|---|---|---|---|
data-trigger-disabled |
present | trigger | Set while disabled keeps the tooltip from opening. |
data-state |
"closed" | "delayed-open" | "instant-open" |
trigger, .tooltip | instant-open when it skipped the delay (another tooltip had just shown); it does not animate in. |
data-side |
"top" | "right" | "bottom" | "left" |
.tooltip, .tooltip-arrow | The side it ended up on. |
data-align |
"start" | "center" | "end" |
.tooltip | |
--transform-origin |
position | .tooltip | The anchor-facing edge; the enter animation scales from it. |
--anchor-width, --anchor-height |
px | .tooltip | The trigger's size. |
--available-width, --available-height |
px | .tooltip | Room to the viewport edge; caps the width. |
--tooltip-arrow-size |
length | .tooltip | Set on the tooltip's class to size the arrow. |
data-popup-open |
present | trigger | While open; the same moment as the trigger's open data-state. |
data-overflowing |
present | .tooltip | Set while the content is taller than the room its side has; the tooltip scrolls and drops its arrow. |
data-instant |
"delay" | "focus" | "dismiss" |
.tooltip, .tooltip-arrow | delay when it skipped the delay, focus when keyboard focus opened it, dismiss when Escape or a press closed it. |
data-open / data-closed |
present | .tooltip, .tooltip-arrow | The open state as two flags; data-closed during the exit animation. |
data-align |
"start" | "center" | "end" |
.tooltip-arrow | The alignment it ended up with. |
data-uncentered |
present | .tooltip-arrow | When the arrow cannot point at the trigger's middle (held off a corner). |
data-anchor-hidden |
present | .tooltip | With hideWhenDetached: while the trigger is scrolled out of view. |
data-starting-style / data-ending-style |
present | .tooltip | On the first frame of the enter animation, and through the exit animation. |
--positioner-width / --positioner-height |
px | .tooltip | The tooltip positions itself, so these are its own size while open. |
Accessibility
- The content has role="tooltip" and the trigger's aria-describedby includes its id while it is open, so a screen reader reads it after the control's name.
- Keyboard focus opens it without delay; focus never moves into it, and it holds nothing focusable.
- Escape closes it without moving focus. A press on the trigger closes it.
- The pointer can move from the trigger onto the tooltip without it closing (WCAG 1.4.13, hoverable), unless disableHoverableContent is set.
- Touch does not open it: put anything a touch user needs in the control's label.
See also
- Button (opens in a new tab): A button or a link that looks like one, in six variants and four sizes.
- Icon (opens in a new tab): An inline stroke icon from the set the templates draw their own controls with, sized in pixels and colored by the text around it.
- Popover (opens in a new tab): Rich content in a floating panel, opened by a trigger, that keeps the page usable.
- HoverCard (opens in a new tab): A preview of what a link points to, shown while the pointer rests on it.