Tooltip
A Tooltip is a small, non-interactive overlay that displays brief informational text when hovering over or focusing on an element. It is built on top of the Popover component.
Key Characteristics
- Hover-Triggered: Automatically shows on hover with configurable delay.
- Non-Interactive: Unlike Popover, tooltips are meant for displaying simple text hints, not interactive content. Still it's possible to interact with the tooltip content if/when needed via
hoverableContentprop. - Accessible: Works with keyboard focus and follows accessibility best practices.
Import
import { Tooltip } from '@andrejground/lab';
Customization
Add your styles and your component is ready to be used.
- MyTooltip.tsx
- MyTooltip.module.scss
import { Tooltip, TooltipProps } from '@andrejground/lab';
import styles from './MyTooltip.module.scss';
type Props = TooltipProps;
function MyTooltip(props: Props) {
return (
<Tooltip
{...props}
classNames={{
...props.classNames,
content: styles.tooltipContent,
}}
/>
);
}
export default MyTooltip;
.tooltipContent {
background-color: var(--tooltip-bg-color);
color: var(--tooltip-text-color);
border: 1px solid var(--tooltip-border-color);
}
Usage
- Preview
- Code
import { Tooltip } from '@andrejground/lab';
export default function App() {
return (
<Tooltip content="This is a tooltip">
<button>Hover me</button>
</Tooltip>
);
}
Placement
- Preview
- Code
import { Tooltip, type TooltipPlacement } from '@andrejground/lab';
const PLACEMENTS: TooltipPlacement[] = [
'top-start',
'top-center',
'top-end',
'bottom-start',
'bottom-center',
'bottom-end',
'right-start',
'right-center',
'right-end',
'left-start',
'left-center',
'left-end',
];
export default function App() {
return (
<>
{PLACEMENTS.map((placement) => (
<Tooltip key={placement} content={placement} placement={placement}>
<button>{placement}</button>
</Tooltip>
))}
</>
);
}
Delay Show
Control the delay before showing the tooltip with delayShow prop.
- Preview
- Code
import { Tooltip } from '@andrejground/lab';
const DELAYS = [0, 300, 500, 1000];
export default function App() {
return (
<>
{DELAYS.map((delay) => (
<Tooltip key={delay} content={`Delay: ${delay}ms`} delayShow={delay}>
<button>{delay}ms delay</button>
</Tooltip>
))}
</>
);
}
Delay Hide
Control the delay before hiding the tooltip with delayHide prop.
- Preview
- Code
import { Tooltip } from '@andrejground/lab';
const DELAYS = [0, 300, 500, 1000];
export default function App() {
return (
<>
{DELAYS.map((delay) => (
<Tooltip key={delay} content={`Delay: ${delay}ms`} delayHide={delay}>
<button>{delay}ms delay</button>
</Tooltip>
))}
</>
);
}
Hoverable Content
Use hoverableContent prop to keep the tooltip visible when hovering over the tooltip content.
- Preview
- Code
import { Tooltip } from '@andrejground/lab';
export default function App() {
return (
<Tooltip
content={
<span>
Hover over me! I stay visible while you interact with this content.
</span>
}
hoverableContent
>
<button>Hover me</button>
</Tooltip>
);
}
Controlled
- Preview
- Code
Open:
falseimport React from 'react';
import { Tooltip } from '@andrejground/lab';
export default function App() {
const [isOpen, setIsOpen] = React.useState(false);
return (
<>
<Tooltip
content="Controlled tooltip"
isOpen={isOpen}
onOpenChange={setIsOpen}
>
<button>Hover me</button>
</Tooltip>
<br />
<div>
Open: <code>{`${isOpen}`}</code>
</div>
</>
);
}
API
Tooltip Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The element that triggers the tooltip |
content | ReactNode | required | Content displayed inside the tooltip |
placement | PopoverPlacement | "top-center" | Preferred placement of the tooltip relative to the trigger |
offset | number | 8 | Distance in pixels between the tooltip and the trigger |
size | PopoverSize | "small" | Controls the width of the tooltip |
isOpen | boolean | - | Controls the tooltip open state (controlled mode) |
isDisabled | boolean | - | Disables the tooltip |
showArrow | boolean | true | Shows an arrow pointing toward the trigger |
shouldFlip | boolean | true | Flips placement when there is not enough space |
shouldCloseOnClickOutside | boolean | true | Closes the tooltip when clicking outside of it |
shouldCloseOnEsc | boolean | true | Closes the tooltip when the Escape key is pressed |
shouldCloseOnTriggerBlur | boolean | true | Closes the tooltip when the trigger loses focus |
openOnFocus | boolean | true | Opens the tooltip when the trigger receives focus |
delayShow | number | 0 | Delay in milliseconds before showing the tooltip |
delayHide | number | hoverableContent ? 200 : 0 | Delay in milliseconds before hiding the tooltip |
hoverableContent | boolean | false | Keeps the tooltip open while hovering over its content |
triggerWrapper | boolean | - | Wraps the trigger in a span instead of using Slot |
fullWidthTriggerWrapper | boolean | - | Makes the trigger wrapper take full width |
onOpen | () => void | - | Callback fired when the tooltip opens |
onClose | () => void | - | Callback fired when the tooltip closes |
onClickOutside | () => void | - | Callback fired when clicking outside the tooltip |
onOpenChange | (isOpen: boolean) => void | - | Callback fired when the open state changes |
onTriggerFocus | () => void | - | Callback fired when the trigger receives focus |
onTriggerBlur | () => void | - | Callback fired when the trigger loses focus |
classNames | TooltipClassNames | - | Custom class names for the tooltip slots |