# Tooltip
A short label for a control, shown on hover and keyboard focus.
```ehtml Example
import { Tooltip, TooltipProvider, TooltipTrigger } from "@elements/ui/tooltip";
import { Button } from "@elements/ui/button";
import { Icon } from "@elements/ui/icon";
...
```
## 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](button): A button or a link that looks like one, in six variants and four sizes.
- [Icon](icon): 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](popover): Rich content in a floating panel, opened by a trigger, that keeps the page usable.
- [HoverCard](hover-card): A preview of what a link points to, shown while the pointer rests on it.