Components
Tooltip
Supplemental text disclosure for hover, focus, and long-press interactions.
When to Use
Use Tooltip for a short text hint that explains a control without requiring
interaction, especially an unfamiliar icon. Use visible text when the
information is important, HoverCard for a richer preview, and Popover when
the floating content contains buttons, links, or other controls.
Features
- Provider-level delay configuration.
- Controlled and uncontrolled open state.
- Opens on pointer hover, keyboard focus-visible, and touch long press.
- Floating UI positioning with side, align, side offset, collision shift, flip, and arrow coordinates.
aria-describedbywiring between trigger and tooltip content.- Portal and arrow parts.
Import
import { Tooltip } from "@flowstack-ui/atom";
Anatomy
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger />
<Tooltip.Portal>
<Tooltip.Content>
<Tooltip.Arrow />
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
</Tooltip.Provider>
API Reference
Provider
Shares open, close, and skip-delay timing between descendant tooltips. Provider renders no DOM element.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | required |
openDelay | number | 400 |
closeDelay | number | 150 |
skipDelay | number | 300 |
ARIA: Provider renders no element and adds no ARIA attributes.
Data attributes: Provider renders no element and exposes none.
Root
Owns one tooltip's open state, timers, Escape dismissal, touch state, and plain or rich hover behavior. Root renders no DOM element.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | required |
open | boolean | - |
defaultOpen | boolean | false |
onOpenChange | (open: boolean) => void | - |
openDelay | number | Provider value or 400 |
closeDelay | number | Provider value or 150 |
disabled | boolean | false |
variant | "plain" | "rich" | "plain" |
ARIA: Root renders no element and adds no ARIA attributes.
Data attributes: Root renders no element and exposes none.
Trigger
Reference element that describes itself with tooltip content while open.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
render | RenderProp | - |
| ARIA attribute | Values |
|---|---|
aria-describedby | Content ID while the tooltip is open |
| Data attribute | Values |
|---|---|
[data-slot] | "tooltip-trigger" |
Portal
Moves Content to another DOM container without rendering a wrapper.
| Prop | Type | Default |
|---|---|---|
container | HTMLElement | null | document.body after mount |
disabled | boolean | false |
ARIA: Portal adds no ARIA attributes.
Data attributes: Portal renders no wrapper and exposes none.
Content
Renders the positioned tooltip text and keeps rich variants open while the pointer moves from Trigger into Content.
| Prop | Type | Default |
|---|---|---|
side | "top" | "right" | "bottom" | "left" | "top" |
align | "start" | "center" | "end" | "center" |
sideOffset | number | 4 |
ariaLabel | string | - |
onMouseEnter | MouseEventHandler<HTMLDivElement> | - |
onMouseLeave | MouseEventHandler<HTMLDivElement> | - |
| ARIA attribute | Values |
|---|---|
role | "tooltip" |
aria-label | Value from ariaLabel when provided |
| Data attribute | Values |
|---|---|
[data-slot] | "tooltip" |
[data-state] | "open" | "closed" |
[data-side] | "top" | "right" | "bottom" | "left" |
[data-variant] | "plain" | "rich" |
[data-positioned] | Present after the first positioning frame |
Arrow
Renders a decorative SVG pointer using the final side chosen after collision
handling. getTooltipArrowGeometry exposes the same geometry for custom arrows.
| Prop | Type | Default |
|---|---|---|
width | number | 10 |
height | number | 5 |
asChild | boolean | false |
render | RenderProp | - |
ARIA: Arrow is decorative and hidden from assistive technology.
| Data attribute | Values |
|---|---|
[data-slot] | "tooltip-arrow" |
[data-side] | "top" | "right" | "bottom" | "left" |
Advanced compound parts can read the Provider, Root, and Content contexts with
their public hooks and providers. getTooltipArrowGeometry returns the same SVG
geometry used by Arrow.
Examples
Basic Tooltip
import { Tooltip } from "@flowstack-ui/atom";
export default function SaveTooltip() {
return (
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button type="button">Save</button>
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content>Save changes</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
</Tooltip.Provider>
);
}
Custom Trigger
import { Tooltip } from "@flowstack-ui/atom";
export default function HelpTooltip() {
return (
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button type="button">Help</button>
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content side="right">More information</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
</Tooltip.Provider>
);
}
Accessibility
Tooltip follows the WAI-ARIA tooltip pattern.
Content is referenced by aria-describedby while open and must remain
non-interactive.
| Key | Description |
|---|---|
Tab | Moving focus to a focus-visible trigger can open the tooltip. |
Shift+Tab | Moving focus away closes the tooltip. |
Escape | Closes the topmost open tooltip immediately. |
Changelog
See CHANGELOG.md.