Tooltip
Tooltip displays short, non-interactive text when its trigger receives a hover or focus event.
Open in Storybook
Import
import { Tooltip } from "@tosui/react";
Basic usage
- Preview
- Code
<Tooltip label="This is a tooltip">
<Button>Hover me</Button>
</Tooltip>
Placement
- Preview
- Code
<HStack gap={4}>
<Tooltip label="Top tooltip" placement="top">
<Button>Top</Button>
</Tooltip>
<Tooltip label="Bottom tooltip" placement="bottom">
<Button>Bottom</Button>
</Tooltip>
<Tooltip label="Left tooltip" placement="left">
<Button>Left</Button>
</Tooltip>
<Tooltip label="Right tooltip" placement="right">
<Button>Right</Button>
</Tooltip>
</HStack>
Delays
openDelay and closeDelay are durations in milliseconds.
- Preview
- Code
<HStack gap={4}>
<Tooltip label="Opens after 500ms" openDelay={500}>
<Button>Open delay</Button>
</Tooltip>
<Tooltip label="Closes after 300ms" closeDelay={300}>
<Button>Close delay</Button>
</Tooltip>
</HStack>
Disabled state
- Preview
- Code
<Tooltip label="This won't show" disabled>
<Button>Disabled tooltip</Button>
</Tooltip>
Controlled state
Pass isOpen when application state owns the open state. Update that state from onOpen and onClose.
function ControlledTooltip() {
const [isOpen, setIsOpen] = useState(false);
return (
<Tooltip
label="Controlled tooltip"
isOpen={isOpen}
onOpen={() => setIsOpen(true)}
onClose={() => setIsOpen(false)}
>
<Button>Controlled</Button>
</Tooltip>
);
}
Common patterns
IconButton with Tooltip
<Tooltip label="Settings">
<IconButton aria-label="Settings">
<SettingsIcon />
</IconButton>
</Tooltip>
Truncated text with a tooltip
<Tooltip label="This is the full text that doesn't fit in the container">
<Text
truncate
maxW="150px"
>
This is the full text that doesn't fit in the container
</Text>
</Tooltip>
Disabled button explanation
<Tooltip label="You need admin permissions to perform this action">
<Box as="span">
<Button disabled>Delete All</Button>
</Box>
</Tooltip>
Props reference
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | - | Tooltip content (required) |
| placement | "top" | "bottom" | "left" | "right" | "top" | Tooltip position |
| openDelay | number | 0 | Delay before showing (ms) |
| closeDelay | number | 0 | Delay before hiding (ms) |
| disabled | boolean | false | Whether tooltip is disabled |
| isOpen | boolean | - | Controlled open state |
| onOpen | () => void | - | Callback when tooltip opens |
| onClose | () => void | - | Callback when tooltip closes |
| className | string | - | Additional CSS class on the tooltip panel |
| children | ReactNode | - | Trigger element (required) |
Accessibility
- The overlay uses
role="tooltip"and has a generated ID. - While the tooltip is open, its focusable trigger receives the tooltip ID in
aria-describedby. - Existing
aria-describedbyIDs remain on the trigger. - If the child has no focusable element, the trigger wrapper receives
tabIndex={0}so keyboard users can open the tooltip. - A disabled tooltip does not add a tab stop or an accessible description.
- The portal renders only in the browser, which keeps server rendering deterministic.
TypeScript
import { Tooltip, type TooltipPlacement, type TooltipProps } from "@tosui/react";