/// Overlay
Tooltip
A hover/focus tip on a dark panel that labels or briefly explains the element it points at.
import { Tooltip, TooltipProvider } from "@protocore/pds";Basics
Wrap any focusable element. content is the tip; children is the trigger, mounted via asChild. Icon-only triggers must still carry their own aria-label.
Placement
side picks the preferred edge; Radix flips it on collision. Keep sideOffset small — the tip should read as attached to the trigger.
Inline explanation
Tooltips can annotate a word inside running text. The panel caps at 280px and never traps focus — content is advisory, never essential.
Cluster health is degraded but still writing blocks.
When to use it
Reach for a Tooltip to label an icon-only control or add a one-line clarification that the user can safely ignore. It appears on hover or focus, holds nothing interactive, and vanishes on the next move.
If the tip contains a link, button, or copy the user must read to proceed, it is not a Tooltip. Use a [Popover](/overlay/popover) for interactive floating content, a [HoverCard](/overlay/hover-card) for a rich hover preview of an entity, and [HelpTip](/inputs/help-tip) for a persistent question-mark affordance beside a form field. Never put anything essential — or anything only reachable by hover — inside a Tooltip.
Usage
Do
- Label icon-only buttons so their action is discoverable.
- Keep content to a single short line — 280px is the ceiling.
- Rely on the built-in 300ms delay so tips don't flash during pointer travel.
- Wrap one focusable trigger so keyboard users get the tip too.
Don't
- Put links, buttons, or form controls inside — use a Popover.
- Hide information the user actually needs to complete a task.
- Attach a tip to a disabled element (it can't receive focus or hover).
- Stack paragraphs of prose into the panel — that's a HoverCard.
Accessibility
| Keys | Action |
|---|---|
| Tab | Moves focus to the trigger, which opens the tip after the delay. |
| Esc | Dismisses the open tip while keeping focus on the trigger. |
- Opens on pointer hover and on keyboard focus; closes on blur, pointer-leave, or Esc.
- Radix links the tip to its trigger via aria-describedby, so screen readers announce it.
- Mount one TooltipProvider near the app root to share a single open-delay / skip-delay timer across every tooltip.
- The tip is advisory only — the interface must remain fully usable without ever revealing it.
Tooltip props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | |
children * | ReactNode | — | The trigger element the tip describes. Wrapped as the Radix trigger via `asChild`. |
className | string | — | |
content * | ReactNode | — | The tip body. Anything renderable; kept short (single line ideal). |
defaultOpen | boolean | — | Uncontrolled initial open state. |
delayDuration | number | 300 | Open delay in ms (overrides the provider's). |
onOpenChange | ((open: boolean) => void) | — | Fires when the open state changes. |
open | boolean | — | Controlled open state. |
side | enum | top | Preferred side of the trigger to render on. |
sideOffset | number | 6 | Pixel gap between trigger and tip. |
style | CSSProperties | — |