Components · Overlays & menus
Tooltip
A small label that names or clarifies a control on hover and focus. It sits on the accent surface — the one place Zetta inverts foreground and background — capped at 200px so it stays a label, never a paragraph.
Preview
Saved 2 minutes ago
Build with the skill
No package to install — hand this to your AI to generate or migrate the component in your stack.
Apply the Zetta "Tooltip" component to this project using the zetta-design-md skill.
WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `tooltip` spec (variants: default) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `tooltip` spec in this project's stack.
AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.
ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility. Anatomy & rules
╭─────────────────╮
│ Tooltip text │ ← tooltip surface (max-width 240px)
╰───────┬─────────╯
▼ ← tooltip-arrow (auto-positioned)
[trigger]
Placement: auto-positioned to avoid viewport clipping. Preferred order: top → bottom → right → left. The arrow always points to the trigger.
| State | Visual |
|---|---|
| Hidden (default) | Not rendered |
| Visible | Dark pill with text, arrow pointing to anchor |
| Entering | Fade in, {motion.duration-fast} delay (150ms hover delay) |
| Exiting | Fade out, {motion.duration-fast} |
When to use
- Icon-only buttons — the tooltip provides the accessible label visible on hover/focus ("Bold", "Delete", "Copy link").
- Truncated text — the tooltip reveals the full string when the container clips it.
- Supplementary hint for a form field or control where a helper text would take too much space.
When not to use
- Critical information — if the user needs the content to proceed, put it inline.
- Error messages — use Inline Message or form field error state.
- Disabled elements — tooltip on a disabled element cannot be triggered by keyboard; the reason for disabling should be visible without a tooltip.
- Long-form content (> 2 sentences) — use a popover or inline help panel instead.
- Mobile-primary interfaces — tooltips are not reliably accessible on touch devices.
Do
- Use tooltip only on interactive elements (buttons, links, inputs, interactive icons).
- Keep tooltip content under 60 characters. For more context, use an inline help icon with a popover.
- Ensure the tooltip
contentprop matches or extends the visible label — never contradicts it.
Don't
- Don't use tooltip to explain disabled elements — explain the reason inline instead.
- Don't put interactive elements (links, buttons) inside the tooltip —
pointerEvents: noneblocks interaction. - Don't rely on tooltip for touch device users — design the interface so it works without them.
- Don't override the 600ms delay to 0ms — instant tooltips are disruptive on icon bars.
- Icon button labels: verb phrase. "Delete item", "Copy to clipboard", "Close panel".
- Truncated text: show the full untruncated string — no rewording.
- Supplementary hints: one short phrase. "Required for billing" not a full sentence with punctuation.
- Casing: sentence case. Never ALL CAPS.
Keyboard
| Key | Behavior |
|---|---|
Tab |
Move focus to the trigger element |
| (trigger focused) | Tooltip becomes visible automatically |
Escape |
Dismiss the tooltip without moving focus from the trigger |
Accessibility
- ARIA pattern: the trigger element uses
aria-describedbypointing to the tooltip container. The tooltip container hasrole="tooltip". - Focus trigger: tooltips must appear on keyboard focus with no delay (accessibility requirement — delay applies to hover only).
- Screen readers:
role="tooltip"causes the content to be announced as a description when the trigger is focused, after the trigger's own label. - Never replace the accessible name: tooltip is a description (
aria-describedby), not a label. An icon button without a visible label must havearia-labelas well — the tooltip is supplementary. - Touch devices: tooltip content must be available through another mechanism (visible label, aria-label) since hover is not available on touch.
Spec
Values and token references resolved straight from the Zetta spec.
tooltip
- backgroundColor
- {colors.surface-header}
- textColor
- {colors.ink}
- borderColor
- {colors.hairline}
- borderWidth
- 1px
- borderRadius
- {rounded.sm}
- fontFamily
- Geist
- fontSize
- 12px
- fontWeight
- 400
- lineHeight
- 1.50
- paddingX
- {spacing.sm}
- paddingY
- {spacing.xs}
- maxWidth
- 240px
- zIndex
- {elevation.z-index.tooltip}
- pointerEvents
- none
- userSelect
- none
- whiteSpace
- normal
- wordBreak
- break-word
tooltip-arrow
- width
- 8px
- height
- 8px
- backgroundColor
- {colors.surface-header}
- borderColor
- {colors.hairline}
- borderWidth
- 1px
- transform
- rotate(45deg)
tooltip-enter
- animation
- tooltip-in {motion.duration-fast} {motion.easing-enter}
- delay
- 600ms
tooltip-exit
- animation
- tooltip-out {motion.duration-fast} {motion.easing-exit}
- delay
- 0ms
tooltip-offset
- gap
- 8px
tooltip-rich
- maxWidth
- 320px
- paddingX
- {spacing.md}
- paddingY
- {spacing.sm}
tooltip-rich-title
- fontFamily
- Geist
- fontSize
- 13px
- fontWeight
- 600
- textColor
- {colors.ink}
- marginBottom
- {spacing.xs}
tooltip-rich-body
- fontFamily
- Geist
- fontSize
- 12px
- fontWeight
- 400
- textColor
- {colors.body}
- lineHeight
- 1.6
tooltip-rich-footer
- marginTop
- {spacing.xs}
- paddingTop
- {spacing.xs}
- borderTopColor
- {colors.hairline}
- borderTopWidth
- 1px
- display
- flex
- gap
- {spacing.xs}
Known gaps
- Interactive tooltip (contains a button or link accessible to pointer users) — a non-standard ARIA pattern; spec deferred.