A label's whisper on hover and focus.
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | — | The hint. One short line, no markup |
| placement | top · bottom · left · right | top | Side the bubble opens toward |
| children | ReactNode | — | The trigger; must be focusable |
| delay | number | 200 | ms before showing on hover (0 on focus) |
| Trigger | Result |
|---|---|
| Hover | Shows after the delay; hides on leave |
| Focus (Tab) | Shows immediately — keyboard parity with hover |
| Escape | Dismisses while the trigger stays focused |
| aria-describedby | Links the trigger to the bubble for screen readers |
A tooltip is supplementary, never essential. It shows on focus as well as hover, so it never hides behind a pointer. If the content is interactive, or the user must read it to succeed, it belongs in the layout — a popover or the page.
Name icon-only buttons. A one-word label turns a glyph into an unambiguous action.
Don't hide paragraphs or steps in a tooltip. Anything essential belongs on the page.
Explain why a control is disabled. The tooltip answers the question before it is asked.
Don't put buttons or links in a tooltip. Interactive content on hover is a menu or popover.
Dense icon rows lean on tooltips so every glyph still says its name.
When a label is clipped, the tooltip reveals it in full on hover or focus.
An info icon offers a definition without spending permanent space on it.
| Token | Value | Role |
|---|---|---|
| --tip-bg | #1A1D27 | Bubble surface (arrow inherits it) |
| --tip-border | #262A34 | Bubble hairline |
| --tip-fg | #E7E9EE | Label text |
| --tip-size | 0.72rem | Label type size |
| --tip-radius | 6px | Corner radius |
| --tip-offset | 8px | Gap from the trigger |
| --tip-delay | 200ms | Hover open delay; 0 on focus |
| --tip-ease | 0.16s | Fade + 3px slide |
<span class="o-tip-wrap"> <button class="o-btn o-btn--icon" aria-describedby="tt1">⧉</button> <span id="tt1" role="tooltip" class="o-tip o-tip--top">Duplicate</span> </span>