Tooltip
Names a control on hover or focus.
Shortcut
nonedefault
keys
Side
topdefault
bottom
right
left
States
label
with shortcut
long label
Usage
When to use it
- Use
- An icon button whose glyph alone could be read two ways: retry or refresh, archive or download.
- Use
- The keyboard shortcut of a button that already has a name.
- Use
- A toolbar of icon buttons, inside one TooltipProvider.
- Not for
- The text explains a term or a rule the person needs. Use Popover.
- Not for
- The content has a link, a button or more than one short phrase. Use Popover.
- Not for
- The text says why a button is disabled. Put it on the page beside the button.
Rules
8 rules
- Must
- Let the tooltip name an icon-only trigger, or give the button an aria-label with the same words. Because a different aria-label has a screen reader say "Copy" while the eye reads "Copy run ID".
- Must
- Write a verb and its object in sentence case under 32 characters, with no period. Because the label becomes the trigger's accessible name, and a sentence wraps into a block that covers the row.
- Must
- Pass a shortcut as shortcut={['⌘', 'C']}, one string per key; never type it into the label. Because typed in, "(⌘C)" joins the trigger's accessible name and is read aloud as part of what the button does.
- Never
- Put a link, a button or a sentence of help in a tooltip; use a PopoverInfo. Because a tooltip never opens on touch and closes as the pointer moves toward the link, so nobody can press it.
- Must
- Show why a button is disabled as text beside it with aria-describedby; never in a tooltip. Because a tooltip never opens on touch, so a phone user meets a dead Publish button with no reason.
- Never
- Add a tooltip to a button with a text label unless it adds the shortcut. Because it repeats the label in a chip that covers the next control and says nothing new.
- Should
- Wrap a row of three or more icon buttons in one TooltipProvider, on Base UI Toolbar when it is role="toolbar".
- Never
- Restyle the chip to paper or add a shadow or an arrow. Because the ink chip is how a Glaze label reads apart from the page, and Glaze draws no shadows.
State order
3 states, highest first
- 1
- instant open
- 2
- delayed open
- 3
- closed
Accessibility
5 checks
- The tooltip is visual; the trigger carries the name, written from the tooltip when it has none.
- Focus opens it at once; hover after 500ms; the next trigger in one provider at once with no fade.
- The chip holds --text-inverse on ink at 18:1 or more in both themes.
- Touch never opens a tooltip; the trigger is still named.
- Forced colors give the chip a 1px outline.
Keyboard
2 keys
- Tab
- Focusing the trigger opens the tooltip at once.
- Escape
- Closes the tooltip and nothing else.
Edge cases
7 edge cases
- 120-character label
- Wraps inside 256px and breaks anywhere.
- Empty label
- Renders nothing and names nothing.
- Link or button as a child
- Dropped with a development error.
- Near a viewport edge
- Flips or shifts to stay 8px inside.
- Inside a dialog
- Portals above it; Escape closes the tooltip only.
- Dark theme
- The chip turns near-white with a dark label: still the inverse of the page.
- Reduced motion
- It cuts in and out.
API
6 props
TooltipContent childrenstring (plus a TooltipShortcut)TooltipContent shortcutstring[]TooltipContent side, align, sideOffsetBase UIdefault'top', 'center', 6TooltipProvider delay, closeDelaynumberdefault500, 0TooltipTrigger renderReactElementTooltipChipstring, shortcut
Tokens
10 tokens
--ink- #050505
--text-inverse- #ffffff
--radius-tag- 6px
--type-label-sm- 500 12px/1.35 var(--font-sans)
--type-code-xs- 400 calc(12px * var(--mono-scale))/1.35 var(--font-mono)
--tooltip-max- 256px
--z-overlay- 50
--dur-overlay- 200ms
--dur-state- 160ms
--ease-out- cubic-bezier(0.2, 0.8, 0.2, 1)