Tooltip
Tooltip adds a short hint to a control that already has a name. Decide first whether the hint should be visible copy instead — a tooltip is the weakest place to put anything a person must read.
Examples
On a button
Pass one focusable element as the child. The component adds aria-describedby to it, so the hint
reaches keyboard and screen-reader users, not only the mouse.
Everyone in the workspace can open this link
On icon-only controls
The icon button's label is its name; the tooltip is the extra sentence. They are different jobs,
and a tooltip must never be the only place a control's name exists.
ArchiveDuplicate
When to use
Use Tooltip for a brief clarification of a control whose purpose is already conveyed by its own name or icon.
Reach for something else when:
- The text is the control's name — use
IconButton'slabel, or a visible label. - The content is long, or contains a link or a button — the bubble is CSS-drawn and cannot hold interactive content. Use Dialog or inline copy.
- The information matters on a touch device — there is no hover there, and a tooltip that only opens on focus is easy to never see.
Accessibility
- The visible bubble is drawn by CSS from a
data-tipattribute, so there is no DOM node holding that text — it is not selectable and cannot be reached by a pointer. A separate hidden<span role="tooltip">carries the same words, and the component merges anaria-describedbyonto your child so assistive technology reads them. - That is why
tipis a plain string rather than a node. - It opens on hover and on focus.
Escapedismisses it without moving the pointer — WCAG 1.4.13 asks exactly that of content shown on hover, and the listener is on the document, because a tip opened by hovering never has focus inside it to receive the key. placementpicks the side (topby default). It is a preference, not a guarantee: the tip flips to the opposite side on its own when the chosen one would be clipped, measured againstvisualViewportso an iOS toolbar or pinch zoom cannot make an off-screen tip look like it fits.- Pass one focusable element. Wrapping a bare
<span>produces a mouse-only tooltip with no keyboard path to it. - In the Next.js App Router, keep the Tooltip and its child in the same client component. The
aria-describedbyis added by cloning your element, and a child that crosses the server/client boundary arrives already serialized: the attribute is missing from the server HTML, React reports a hydration mismatch, and — because React does not patch attribute mismatches — the description never reaches the DOM at all. A'use client'directive on the file that renders both is the fix.
Props
| Name | Type | Required | Description |
|---|---|---|---|
tip | string | Required | Short, non-interactive text shown for the target. |
children | ReactNode | Required | The target element. Pass one focusable React element for full keyboard support. |
placement | TooltipPlacement | — | Side of the target to draw the tip on. Default `"top"`. The tip flips to the opposite side on its own when the chosen one would be clipped by the viewport, so this is a preference. |
Plain HTML
The wrapper carries the text in data-tip; CSS draws the bubble from it:
<span class="lyra-tooltip" data-tip="Everyone in the workspace can open this link">
<button
class="lyra-btn lyra-btn--secondary lyra-btn--md"
type="button"
aria-describedby="tip-share"
>
Copy share link
</button>
<span id="tip-share" role="tooltip" hidden>Everyone in the workspace can open this link</span>
</span>