Tooltip
Tooltip shows a Windows 98 info popup for hover and focus targets. Compose a TooltipTrigger around the target with a TooltipContent for the popup.
Composition
Use the following composition to build a Tooltip:
Tooltip
├── TooltipTrigger
└── TooltipContentProps
Tooltip
The root. Owns visibility state; renders no element of its own.
| Prop | Type | Default | Description |
|---|---|---|---|
delay | number | 400 | Delay before showing on hover/focus, in milliseconds. |
open | boolean | - | Visible state (controlled). |
defaultOpen | boolean | false | Initial visible state (uncontrolled). |
onOpenChange | (open: boolean) => void | - | Called when the tooltip shows or hides. |
TooltipTrigger
Wraps the hover/focus target in an inline-flex span and anchors the popup. Accepts native span props.
TooltipContent
The portalled popup. Accepts native span props plus:
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'bottom' | 'left' | 'right' | 'top' | Preferred placement, with viewport flipping. |
Examples
Hover and focus hints
import { Button, Tooltip, TooltipContent, TooltipTrigger } from '@murasaki-io/react98'
export function TooltipBasicDemo(): React.ReactElement {
return (
<div className="flex gap-3">
<Tooltip delay={150}>
<TooltipTrigger>
<Button>Save</Button>
</TooltipTrigger>
<TooltipContent>Save changes</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger>
<Button>Help</Button>
</TooltipTrigger>
<TooltipContent side="bottom">Opens below the control</TooltipContent>
</Tooltip>
</div>
)
}Viewport edge detection
import { Button, Tooltip, TooltipContent, TooltipTrigger } from '@murasaki-io/react98'
const TOOLTIPS = [
{
id: 'top',
label: 'Top',
side: 'top' as const,
text: 'Tooltip prefers the top edge and flips when space runs out.',
style: { gridColumn: 2, gridRow: 1, justifySelf: 'center' },
},
{
id: 'left',
label: 'Left',
side: 'left' as const,
text: 'Tooltip prefers the left edge and repositions if needed.',
style: { gridColumn: 1, gridRow: 2, justifySelf: 'start' },
},
{
id: 'right',
label: 'Right',
side: 'right' as const,
text: 'Tooltip prefers the right edge and stays within the viewport.',
style: { gridColumn: 3, gridRow: 2, justifySelf: 'end' },
},
{
id: 'bottom',
label: 'Bottom',
side: 'bottom' as const,
text: 'Tooltip prefers the bottom edge and flips upward near the boundary.',
style: { gridColumn: 2, gridRow: 3, justifySelf: 'center' },
},
]
export function TooltipEdgeTestDemo(): React.ReactElement {
return (
<div
className="box-border grid gap-3 w-full h-full min-h-0 p-3"
style={{
gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
gridTemplateRows: 'repeat(3, minmax(0, 1fr))',
}}
>
{TOOLTIPS.map(tooltip => (
<div key={tooltip.id} style={tooltip.style}>
<Tooltip delay={100}>
<TooltipTrigger>
<Button>{tooltip.label}</Button>
</TooltipTrigger>
<TooltipContent side={tooltip.side}>{tooltip.text}</TooltipContent>
</Tooltip>
</div>
))}
</div>
)
}ARIA
The trigger gains aria-describedby while the tooltip is visible, pointing at the role="tooltip" popup.
Keyboard
Focusing the trigger shows the tooltip after the configured delay. Escape dismisses the visible tooltip.
SSR
Tooltip portals after mount. Keep the trigger markup stable across server and client.
Last updated on