Tooltip
A short label that appears on hover or focus: the name of an icon button, its shortcut, or the full text of something clipped. It never holds anything the person must read to finish a task.
Playground
Change the controls to try each prop. The preview holds the tooltip open; on a page it opens on hover and on keyboard focus. The code under the preview updates as you go and lists only the props you changed.
import { TooltipContent } from '@/ui/tooltip';<TooltipContent> Archive</TooltipContent>Default
Hover the button, or Tab to it. An icon button always has a tooltip, and its text is the button's label, so what you see is what a screen reader says.
import { ArchiveIcon } from '@phosphor-icons/react';
import { IconButton } from '@/ui/button';
export default function TooltipDefault() {
return (
<IconButton label="Archive">
<ArchiveIcon />
</IconButton>
);
}Placement
The tooltip opens above its trigger, 4px away, and flips to the side with room. Pick another side when the default would cover something: below near the top edge, to the right in a collapsed sidebar.
import { ArchiveIcon, CopyIcon, FunnelSimpleIcon } from '@phosphor-icons/react';
import { IconButton } from '@/ui/button';
export default function TooltipPlacement() {
return (
<div className="flex items-center gap-300">
<IconButton label="Archive">
<ArchiveIcon />
</IconButton>
<IconButton label="Copy email" tooltipSide="bottom">
<CopyIcon />
</IconButton>
<IconButton label="Filter" tooltipSide="right">
<FunnelSimpleIcon />
</IconButton>
</div>
);
}With a shortcut
Pass shortcut and the keys follow the label, one chip per key, modifiers first. Mod is ⌘ on Apple platforms and Ctrl elsewhere. The trigger also gets aria-keyshortcuts, so screen readers announce the keys. Hint puts the same tooltip on any other trigger, such as a button with a text label.
import { ArchiveIcon, ArrowsClockwiseIcon, NotePencilIcon } from '@phosphor-icons/react';
import { Button, IconButton } from '@/ui/button';
import { Hint } from '@/ui/tooltip';
export default function TooltipShortcut() {
return (
<div className="flex items-center gap-300">
<IconButton label="Archive" shortcut={['E']}>
<ArchiveIcon />
</IconButton>
<IconButton label="Log activity" shortcut={['Mod', 'E']}>
<NotePencilIcon />
</IconButton>
<Hint label="Sync now" shortcut={['R']}>
<Button>
<ArrowsClockwiseIcon />
Sync now
</Button>
</Hint>
</div>
);
}Clipped text
TruncatedText shows the full text in a tooltip only while the text is cut off. The tooltip wraps up to 320px wide.
import { TruncatedText } from '@/ui/truncated-text';
export default function TooltipClipped() {
return (
<TruncatedText text="Senior Data Engineer, Platform and Infrastructure (London, hybrid)" className="block w-56 text-body font-medium" />
);
}Record peek
A record opened beside the list it came from: an application, a target pursuit, a meeting. The list stays live; the address carries the record, so the peek can be shared and Back closes it.
Banner
A full-width strip for a state that covers everything below it: the whole app when you are offline, or a whole record when it is archived or must not be contacted. The largest of three message levels.