Tooltip
Names an icon button on hover or focus.
Examples
Shortcut
nonedefault
keys
Side
topdefault
bottom
right
left
States
rest
hover
focus-visible
Usage
When to use it
- Use
- An icon button whose glyph alone may be read two ways: reassign or refresh, archive or download.
- Use
- Showing the keyboard shortcut for 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 text says why a button is disabled. Use Field.
- Not for
- The content has a link, a button or more than one sentence. Use Popover.
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 ticket ID".
- Must
- Write a verb and its object in sentence case under 32 characters, 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 Popover. Because a tooltip never opens on touch and closes as the pointer moves to 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 that already has a text label, unless it adds a shortcut. Because it repeats the label in a popup that covers the next control and says nothing new.
- Should
- Wrap three or more icon buttons in one row in a single TooltipProvider.
- Must
- Build a role="toolbar" row on Base UI Toolbar with Toolbar.Button triggers, or drop the role. Because role="toolbar" tells a screen reader user to move with arrow keys, and a plain div ignores them.
Accessibility
7 checks
- The tooltip is visual only; the trigger carries its own name, written from the tooltip when none exists.
- Focus opens the tooltip at once; hover opens it after 500ms.
- Moving to the next trigger inside one TooltipProvider opens it with no delay and no fade.
- Escape closes the tooltip and nothing else; Enter or Space runs the button and closes it.
- The popup and the shortcut keys are not announced.
- Touch never opens a tooltip; the trigger is still named.
- Forced colors give the chip and each key a 1px outline.
Edge cases
10 edge cases
- 120-character label
- Wraps inside 256px and breaks anywhere.
- Toolbar of four
- The first opens after 500ms, the rest at once with no fade.
- Right to left
- The chip computes RTL and the shortcut sits at the inline end.
- Touch
- Tap runs the button and never opens the tooltip.
- One-letter label
- Renders a 24px chip and names the trigger R. Write a verb phrase.
- 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.
- Reduced motion
- It cuts in; it never grew.
API
6 props
TooltipContent childrenstring (plus a TooltipShortcut)TooltipContent shortcutstring[]TooltipContent side, align, sideOffsetBase UIdefault'top', 'center', 6TooltipProvider delay / closeDelaynumberdefault500 / 0Tooltip open, defaultOpen, onOpenChangeBase UITooltipTrigger renderReactElement
Tokens
11 tokens
--surface-page- var(--paper)
--text-1- var(--ink)
--radius-soft- 6px
--radius-inner- 4px
--type-label-sm- 400 12px/16px var(--font-sans)
--elev-overlay- 0 0 0 1px var(--line-frame), 0 12px 24px -12px oklch(var(--text-on-field-c) / var(--shadow-alpha))
--dur-fast- 120ms
--ease-step- cubic-bezier(0.2, 0, 0, 1)
--text-2- oklch(var(--ink-c) / 0.80)
--type-tag- var(--type-code-sm)
--tooltip-max- 256px