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 children
string (plus a TooltipShortcut)
TooltipContent shortcut
string[]
TooltipContent side, align, sideOffset
Base UI default 'top', 'center', 6
TooltipProvider delay, closeDelay
number default 500, 0
TooltipTrigger render
ReactElement
TooltipChip
string, 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)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.