# Tooltip

A tooltip names an icon-only control when you hover it or reach it with the keyboard.

## When to use

- To show the name of an icon-only control, like copy, close or more. [Icon button](/components/icon-button/) does this for you.
- To show a keyboard shortcut next to that name, like *Search ⌘K*.

## When not to use

- For anything someone needs to finish a task. Tooltips don't show on touch screens, so put it on the page.
- For a sentence or two of explanation, like what slippage means. Use a popover the reader opens with a click.
- For anything with a link or a button inside. A tooltip closes as soon as the pointer leaves.
- On a control that already shows its label, or on plain text that can't be focused.

## Anatomy

## Icon button

Every Icon button shows its `label` in a tooltip, so most screens never use Tooltip directly. Turn it off with `tooltip={false}` when the same words sit right beside the button, and move it with `tooltipSide` when the top is crowded.

## Placement

Tooltips open above the trigger by default, 8px away, with no arrow. They flip to the other side when there's no room. Use `side="right"` on a left rail and `side="bottom"` for controls at the top of the screen.

## Hint

`hint` adds a shortcut or a short status after the label, in `color/text/inverse-muted-foreground`. Write shortcuts the way the keys read: *⌘K*, *G then H*.

## Long labels

## Behaviour

- Resting the pointer opens a tooltip after 400ms. The wait tells pausing from passing, so a pointer crossing the screen doesn't flash labels on every control it touches.
- Once one is open, the next opens at once, and for 300ms after it closes. Sweeping along a toolbar never pays the wait twice.
- Keyboard focus opens it straight away: <kbd>Tab</kbd>, or arrow keys inside a toolbar. Focus from a click, or a dialog focusing its first control, doesn't.
- Moving away closes it, and the 100ms fade gives the pointer time to cross the 8px gap onto it, so it stays open while the pointer is on it.
- A click closes it until the pointer leaves the trigger. <kbd>Escape</kbd> closes it without moving focus.
- The first tooltip fades in over 150ms, growing from 96% and 2px out of the trigger on a steep ease-out. It fades out in 100ms. While you sweep along a row, one bubble follows the pointer: the next tooltip starts where the last one was and glides to its button in 200ms, resizing to its label. It only glides on the same side and within 160px; further away, or when it flips side, it swaps in place.
- With reduced motion it only fades, with no scale, movement or glide.

| Key | Action |
| --- | --- |
| <kbd>Tab</kbd> | Moves focus to the trigger and shows its tooltip. |
| Arrow keys | In a toolbar that moves focus with arrows, shows the newly focused button's tooltip. |
| <kbd>Escape</kbd> | Hides the tooltip and keeps focus on the trigger. |

### When pointing is the task

The wait protects people from controls they're only passing. When someone points somewhere just to read the tooltip, like a point on a chart, a slider's value while dragging, or a timeline while scrubbing, open it at once with `delayDuration={0}` on that `Tooltip`.

## Content

- Name the action in a few words, in sentence case, with no full stop: *Copy address*, *View on explorer*.
- Use the same words as the control's accessible name, so what people see is what screen readers say.
- Keep it under 240px. If a label wraps, it is probably an explanation.

## Accessibility

- The tooltip has `role="tooltip"` and describes its trigger while it's open. On an Icon button the text repeats the button's name, so Icon button leaves the description off.
- Screen readers and touch screens may never show it. The trigger needs its own accessible name.
- Tooltips mount at the end of the page, so a card's `overflow: hidden` never clips them.

## Props

`Tooltip` wraps one trigger and its content. `TooltipProvider` sits at the root of the hub; a `Tooltip` outside it makes its own.

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `side` | `"top"` \| `"right"` \| `"bottom"` \| `"left"` | `"top"` | On `TooltipContent`. Flips when there's no room. |
| `sideOffset` | `number` | `8` | On `TooltipContent`. The gap to the trigger. |
| `hint` | `ReactNode` | | On `TooltipContent`. Dimmed text after the label. |
| `container` | `HTMLElement` | `document.body` | On `TooltipContent`. Where the tooltip mounts. |
| `open`, `onOpenChange` | | | On `Tooltip`, to control it. `open={false}` keeps it shut. |
| `delayDuration` | `number` | `400` | On `TooltipProvider` or `Tooltip`. `0` when pointing is the task. |
| `skipDelayDuration` | `number` | `300` | On `TooltipProvider`. How long the next tooltip skips the wait. |

```tsx
<Tooltip>
  <TooltipTrigger asChild>
    <button aria-label="Search">…</button>
  </TooltipTrigger>
  <TooltipContent side="right" hint="⌘K">
    Search
  </TooltipContent>
</Tooltip>
```

## Related

- An [Icon button](/components/icon-button/) shows its label in a tooltip.
- A [Button](/components/button/) shows its label all the time.
