Components
A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
Playground
asChild so the tooltip attaches to your own element. The showcase layout already mounts TooltipProvider, so tooltips work anywhere in the tree without extra setup.import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@workspace/ui/components/tooltip"
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">Hover</Button>
</TooltipTrigger>
<TooltipContent>Add to library</TooltipContent>
</Tooltip>side prop on TooltipContent — top (the default), right, bottom or left. When there is not enough room, Radix flips the tooltip to the opposite side automatically.<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">Top</Button>
</TooltipTrigger>
<TooltipContent side="top">Tooltip on top</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">Right</Button>
</TooltipTrigger>
<TooltipContent side="right">Tooltip on the right</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">Bottom</Button>
</TooltipTrigger>
<TooltipContent side="bottom">Tooltip on the bottom</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">Left</Button>
</TooltipTrigger>
<TooltipContent side="left">Tooltip on the left</TooltipContent>
</Tooltip>Kbd inside TooltipContent to document a shortcut. The content restyles the kbd for the inverted surface and trims its own end padding via has-data-[slot=kbd]:pe-1.5, so no extra classes are needed.<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">
<FloppyDiskIcon data-icon="inline-start" />
Save
</Button>
</TooltipTrigger>
<TooltipContent>
Save changes <Kbd>⌘S</Kbd>
</TooltipContent>
</Tooltip><Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" aria-label="Add to library">
<PlusIcon />
</Button>
</TooltipTrigger>
<TooltipContent>Add to library</TooltipContent>
</Tooltip>span and let the wrapper be the trigger — a good place to explain why the action is unavailable.<Tooltip>
<TooltipTrigger asChild>
<span tabIndex={0}>
<Button variant="outline" disabled>
Publish
</Button>
</span>
</TooltipTrigger>
<TooltipContent>Fix the validation errors first</TooltipContent>
</Tooltip>side is physical: "left" stays on the left regardless of direction.<div dir="rtl">
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline">حفظ</Button>
</TooltipTrigger>
<TooltipContent>
حفظ التغييرات <Kbd>⌘S</Kbd>
</TooltipContent>
</Tooltip>
</div>TooltipProvider near the root of the app — it shares timing state so pointing from one trigger to the next opens instantly. This design system sets delayDuration to 0 by default. The showcase already mounts it in app/layout.tsx; a new consumer app sets it up once:import { TooltipProvider } from "@workspace/ui/components/tooltip"
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
)
}| Part | Prop | Type | Default |
|---|---|---|---|
| Tooltip | open | boolean | — |
| Tooltip | defaultOpen | boolean | false |
| Tooltip | onOpenChange | (open: boolean) => void | — |
| TooltipContent | side | "top" | "right" | "bottom" | "left" | "top" |
| TooltipContent | align | "start" | "center" | "end" | "center" |
| TooltipContent | sideOffset | number | 0 |
| TooltipProvider | delayDuration | number | 0 |
Tokens used
7 design tokens consumed by the Tooltip component.
--foreground
Foreground
--background
Background
--text-xs
Text Extra Small (12px)
--radius-md
Radius 0.8× (8px)
--radius-sm
Radius 0.6× (6px)
--container-xs
Container XS (320px)
--spacing
Spacing unit (4px)