components / overlay
Tooltip
Show a short hint on hover or keyboard navigation.
tooltip-default.tsx
import { BoldIcon, ItalicIcon, LinkIcon, UnderlineIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Tip, TooltipProvider } from "@/components/ui/tooltip";
const tools = [
{ label: "Bold", Icon: BoldIcon },
{ label: "Italic", Icon: ItalicIcon },
{ label: "Underline", Icon: UnderlineIcon },
{ label: "Link", Icon: LinkIcon },
];
export default function TooltipDefault() {
return (
<TooltipProvider>
<div className="flex gap-1 rounded-lg border bg-background p-1">
{tools.map(({ label, Icon }) => (
<Tip content={label} key={label}>
<Button aria-label={label} size="icon-sm" variant="ghost">
<Icon aria-hidden="true" />
</Button>
</Tip>
))}
</div>
</TooltipProvider>
);
}Installation
$ npx shadcn@latest add https://cd-ui.vercel.app/r/tooltip.jsonfirst time? set up components.json and the theme first: see installation.
Usage
import { Tip } from "@/components/ui/tooltip"
<Tip content="Bold">
<Button aria-label="Bold" size="icon-sm" variant="ghost">B</Button>
</Tip>
// full control
import { Tooltip, TooltipPopup, TooltipTrigger } from "@/components/ui/tooltip"
<Tooltip>
<TooltipTrigger aria-label="Help" onClick={openHelp} render={<Button />}>?</TooltipTrigger>
<TooltipPopup arrow side="bottom">help</TooltipPopup>
</Tooltip>Examples
Parts, sides, and arrow
The parts give full control. arrow adds a pointer to the trigger.
tooltip-parts.tsx
import { Button } from "@/components/ui/button";
import { Tooltip, TooltipPopup, TooltipTrigger } from "@/components/ui/tooltip";
export default function TooltipParts() {
return (
<div className="flex flex-wrap justify-center gap-3">
{(["top", "right", "bottom", "left"] as const).map((side) => (
<Tooltip key={side}>
<TooltipTrigger render={<Button variant="outline" />}>{side}</TooltipTrigger>
<TooltipPopup arrow side={side}>
Tooltip on the {side}
</TooltipPopup>
</Tooltip>
))}
</div>
);
}API
TooltipProvider
Base UI · Tooltip.ProviderOptional. Shares the delay between neighboring tooltips: after the first, the next ones open at once.
| prop | type | default |
|---|---|---|
delayDelay (ms) of the first tooltip. | number | 250 |
closeDelayDelay (ms) before closing. | number | 0 |
Tip
Shortcut: wraps the trigger element and shows content in a tooltip. Same as Tooltip + TooltipTrigger + TooltipPopup; accepts side, sideOffset, and arrow too.
| prop | type | default |
|---|---|---|
contentWhat the tooltip shows. | ReactNode | - |
childrenThe trigger: a single element. | ReactElement | - |
Tooltip · TooltipTrigger
Base UI · Tooltip.Root · Tooltip.TriggerRoot and trigger.
| prop | type | default |
|---|---|---|
renderSwaps the rendered element while keeping behavior and style (e.g. become an | ReactElement | (props) => ReactElement | - |
TooltipPopup
Base UI · Tooltip.PopupSmall bubble in the Material style. Grows from the trigger in 160ms; the following ones appear without animation.
| prop | type | default |
|---|---|---|
sidePreferred side. | "top" | "bottom" | "left" | "right" | "top" |
sideOffsetDistance from the trigger (px). | number | 8 |
arrowShows a pointer toward the trigger. | boolean | false |
classNameExtra classes, merged with | string | - |
Accessibility
- Also opens with keyboard focus.
- Don't put interactive content inside the tooltip: use a Popover.