import { Tooltip, Button } from 'reshaped';
function Example() {
return (
<Tooltip text="This is helpful information" position="top">
{(attributes) => (
<Button attributes={attributes}>Hover me</Button>
)}
</Tooltip>
);
}
Usage
Tooltips display brief, contextual information when users hover over or focus on an element. They automatically position themselves and disappear when the user moves away.
Props
Content to display in the tooltip.<Tooltip text="Click to edit">
children
(attributes: TriggerAttributes) => React.ReactNode
required
Render function that provides attributes for the trigger element.<Tooltip text="Help">
{(attributes) => <Button attributes={attributes}>?</Button>}
</Tooltip>
Position relative to the trigger element.Options: "bottom", "bottom-start", "bottom-end", "top", "top-start", "top-end", "start", "start-top", "start-bottom", "end", "end-top", "end-bottom"Default: "top"
Color scheme for the tooltip.Options: "inverted", "dark"
Controlled state for tooltip visibility.<Tooltip text="Info" active={showTooltip}>
Gap between trigger and tooltip in pixels.
Shift the tooltip on the secondary axis.
Maximum width for the tooltip content.<Tooltip contentMaxWidth="200px" text="Very long tooltip text...">
Custom z-index for the tooltip.
Callback when the tooltip opens.
Callback when the tooltip closes.
Hide tooltip when hovering over it.
containerRef
React.RefObject<HTMLElement>
Container element for positioning.
positionRef
React.RefObject<HTMLElement>
Element to calculate position against.
Position coordinates when there’s no trigger element.
Additional CSS class for the tooltip content.
Additional HTML attributes for the tooltip content.
instanceRef
React.Ref<TooltipInstance>
Ref to access tooltip methods.
Examples
Basic Tooltip
<Tooltip text="Click to edit this item">
{(attributes) => (
<Button attributes={attributes} icon={IconEdit} variant="ghost" />
)}
</Tooltip>
Positions
<View direction="row" gap={2}>
<Tooltip text="Top" position="top">
{(attributes) => <Button attributes={attributes}>Top</Button>}
</Tooltip>
<Tooltip text="Bottom" position="bottom">
{(attributes) => <Button attributes={attributes}>Bottom</Button>}
</Tooltip>
<Tooltip text="Start" position="start">
{(attributes) => <Button attributes={attributes}>Start</Button>}
</Tooltip>
<Tooltip text="End" position="end">
{(attributes) => <Button attributes={attributes}>End</Button>}
</Tooltip>
</View>
Color Variants
<View direction="row" gap={2}>
<Tooltip text="Inverted tooltip" color="inverted">
{(attributes) => <Button attributes={attributes}>Inverted</Button>}
</Tooltip>
<Tooltip text="Dark tooltip" color="dark">
{(attributes) => <Button attributes={attributes}>Dark</Button>}
</Tooltip>
</View>
Icon Button with Tooltip
import IconSave from 'reshaped/icons/Save';
import IconUndo from 'reshaped/icons/Undo';
import IconRedo from 'reshaped/icons/Redo';
function Toolbar() {
return (
<View direction="row" gap={1}>
<Tooltip text="Save (⌘S)" position="bottom">
{(attributes) => (
<Button
attributes={attributes}
icon={IconSave}
variant="ghost"
onClick={handleSave}
/>
)}
</Tooltip>
<Tooltip text="Undo (⌘Z)" position="bottom">
{(attributes) => (
<Button
attributes={attributes}
icon={IconUndo}
variant="ghost"
onClick={handleUndo}
/>
)}
</Tooltip>
<Tooltip text="Redo (⌘⇧Z)" position="bottom">
{(attributes) => (
<Button
attributes={attributes}
icon={IconRedo}
variant="ghost"
onClick={handleRedo}
/>
)}
</Tooltip>
</View>
);
}
Multiline Tooltip
<Tooltip
text="This is a longer tooltip that will wrap to multiple lines when it exceeds the maximum width"
contentMaxWidth="200px"
>
{(attributes) => (
<Button attributes={attributes}>Info</Button>
)}
</Tooltip>
Disabled Tooltip
function ConditionalTooltip({ hasPermission }) {
return (
<Tooltip
text="You don't have permission to edit"
disabled={hasPermission}
>
{(attributes) => (
<Button
attributes={attributes}
disabled={!hasPermission}
onClick={handleEdit}
>
Edit
</Button>
)}
</Tooltip>
);
}
Help Icons
import IconHelp from 'reshaped/icons/HelpCircle';
function FormField() {
return (
<View gap={1}>
<View direction="row" gap={1} align="center">
<Text variant="body-3" weight="bold">API Key</Text>
<Tooltip text="Your API key can be found in Settings > Integrations">
{(attributes) => (
<Button
attributes={attributes}
icon={IconHelp}
variant="ghost"
size="small"
/>
)}
</Tooltip>
</View>
<TextField name="apiKey" />
</View>
);
}
Truncated Text
function TruncatedWithTooltip({ text }) {
const [isTruncated, setIsTruncated] = React.useState(false);
const textRef = React.useRef();
React.useEffect(() => {
const element = textRef.current;
setIsTruncated(element.scrollWidth > element.clientWidth);
}, [text]);
return (
<Tooltip text={text} disabled={!isTruncated}>
{(attributes) => (
<Text
attributes={{ ...attributes, ref: textRef }}
attributes={{ style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }}
>
{text}
</Text>
)}
</Tooltip>
);
}
Status Indicators
function StatusBadge({ status }) {
const statusConfig = {
active: { color: 'positive', text: 'Service is running normally' },
warning: { color: 'warning', text: 'Degraded performance detected' },
error: { color: 'critical', text: 'Service is currently down' },
};
const config = statusConfig[status];
return (
<Tooltip text={config.text}>
{(attributes) => (
<View
attributes={attributes}
width="12px"
height="12px"
borderRadius="full"
backgroundColor={config.color}
/>
)}
</Tooltip>
);
}
Controlled Tooltip
function ControlledTooltipExample() {
const [showTooltip, setShowTooltip] = React.useState(false);
return (
<View gap={3}>
<Tooltip
text="This tooltip is controlled"
active={showTooltip}
>
{(attributes) => (
<Button attributes={attributes}>Hover me</Button>
)}
</Tooltip>
<Button onClick={() => setShowTooltip(!showTooltip)}>
Toggle Tooltip
</Button>
</View>
);
}
With Popover
// Tooltip on the trigger, Popover for detailed content
<Tooltip text="Click for more options" position="top">
{(tooltipAttributes) => (
<Popover position="bottom">
<Popover.Trigger>
{(popoverAttributes) => (
<Button attributes={{ ...tooltipAttributes, ...popoverAttributes }}>
Options
</Button>
)}
</Popover.Trigger>
<Popover.Content>
<View gap={2} padding={3}>
<Text>Detailed options here</Text>
</View>
</Popover.Content>
</Popover>
)}
</Tooltip>
Chart Data Points
function DataPoint({ value, label }) {
return (
<Tooltip text={`${label}: ${value}`}>
{(attributes) => (
<View
attributes={attributes}
width="8px"
height="8px"
borderRadius="full"
backgroundColor="primary"
attributes={{
...attributes,
style: { cursor: 'pointer' },
}}
/>
)}
</Tooltip>
);
}
Best Practices
- Keep tooltip text concise (1-2 short sentences)
- Use tooltips for supplementary information, not critical content
- Don’t use tooltips on disabled elements that aren’t focusable
- Ensure trigger elements are keyboard accessible
- Don’t hide important actions behind tooltips
- Use consistent positioning across your interface
- Avoid nesting interactive elements inside tooltips
Accessibility
- Tooltips appear on both hover and keyboard focus
- Content is announced to screen readers via
aria-describedby
- Pressing Escape dismisses the tooltip
- Tooltip doesn’t trap focus or block interaction
- Ensure tooltip trigger is keyboard accessible
- Don’t rely solely on tooltips for critical information
- Adequate contrast between tooltip and background