"use client";
import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
export function TooltipDemo() { return ( <Tooltip> <TooltipTrigger render={<Button variant="tertiary" />}> Hover </TooltipTrigger> <TooltipContent> <p>Add to library</p> </TooltipContent> </Tooltip> );}pnpm dlx shadcn@latest add @herocn/tooltipTooltipProvider to the root of your app.import { TooltipProvider } from "@/components/ui/tooltip"
export default function RootLayout({ children,}: Readonly<{ children: React.ReactNode}>) { return ( <html lang="en"> <body> <TooltipProvider>{children}</TooltipProvider> </body> </html> )}import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip"<Tooltip> <TooltipTrigger render={<Button variant="outline" />}>Hover</TooltipTrigger> <TooltipContent> <p>Add to library</p> </TooltipContent></Tooltip>Use the following composition to build a Tooltip:
Tooltip├── TooltipTrigger└── TooltipContentUse the side prop to change the position of the tooltip.
"use client";
import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
export function TooltipSides() { return ( <div className="flex flex-wrap gap-2"> {(["left", "top", "bottom", "right"] as const).map((side) => ( <Tooltip key={side}> <TooltipTrigger render={<Button variant="tertiary" className="w-fit capitalize" />} > {side} </TooltipTrigger> <TooltipContent side={side}> <p>Add to library</p> </TooltipContent> </Tooltip> ))} </div> );}Use the withArrow prop to add arrow to the tooltip
"use client";
import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
export function ToolTipArrow() { return ( <div className="flex flex-wrap gap-2"> {(["left", "top", "bottom", "right"] as const).map((side) => ( <Tooltip key={side}> <TooltipTrigger render={<Button variant="tertiary" className="w-fit capitalize" />} > {side} </TooltipTrigger> <TooltipContent withArrow side={side}> <p>This tooltip has an arrow</p> </TooltipContent> </Tooltip> ))} </div> );}"use client";
import { SaveIcon } from "lucide-react";
import { Button } from "@/components/ui/button";import { Kbd } from "@/components/ui/kbd";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
export function TooltipKeyboard() { return ( <Tooltip> <TooltipTrigger render={<Button variant="tertiary" size="icon-sm" />}> <SaveIcon /> </TooltipTrigger> <TooltipContent> Save Changes <Kbd>S</Kbd> </TooltipContent> </Tooltip> );}Show a tooltip on a disabled button by wrapping it with a span.
"use client";
import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
export function TooltipDisabled() { return ( <Tooltip> <TooltipTrigger render={<span className="inline-block w-fit" />}> <Button variant="tertiary" disabled> Disabled </Button> </TooltipTrigger> <TooltipContent> <p>This feature is currently unavailable</p> </TooltipContent> </Tooltip> );}To enable RTL support in shadcn/ui, see the RTL configuration guide.
"use client";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger,} from "@/components/ui/tooltip";
const translations: Translations = { en: { dir: "ltr", values: { content: "Add to library", "inline-start": "Inline Start", left: "Left", top: "Top", bottom: "Bottom", right: "Right", "inline-end": "Inline End", }, }, ar: { dir: "rtl", values: { content: "إضافة إلى المكتبة", "inline-start": "بداية السطر", left: "يسار", top: "أعلى", bottom: "أسفل", right: "يمين", "inline-end": "نهاية السطر", }, }, he: { dir: "rtl", values: { content: "הוסף לספרייה", "inline-start": "תחילת השורה", left: "שמאל", top: "למעלה", bottom: "למטה", right: "ימין", "inline-end": "סוף השורה", }, },};
const physicalSides = ["left", "top", "bottom", "right"] as const;const logicalSides = ["inline-start", "inline-end"] as const;
export function TooltipRtl() { const { dir, language, t } = useTranslation(translations, "ar");
return ( <div lang={language} dir={dir} className="grid gap-4"> <div className="flex flex-wrap justify-center gap-2"> {physicalSides.map((side) => ( <Tooltip key={side}> <TooltipTrigger render={<Button variant="tertiary" />}> {t[side]} </TooltipTrigger> <TooltipContent side={side} dir={dir}> {t.content} </TooltipContent> </Tooltip> ))} </div> <div className="flex flex-wrap justify-center gap-2"> {logicalSides.map((side) => ( <Tooltip key={side}> <TooltipTrigger render={<Button variant="tertiary" />}> {t[side]} </TooltipTrigger> <TooltipContent side={side} dir={dir}> {t.content} </TooltipContent> </Tooltip> ))} </div> </div> );}The tooltip is built on Base UI Tooltip. TooltipContent sets default positioning and passes the remaining props to the popup.
| Prop | Type | Default |
|---|---|---|
| align | "start" | "center" | "end" | "center" |
Horizontal alignment of the tooltip relative to the anchor. | ||
| alignOffset | number | 0 |
Offset along the alignment axis. | ||
| side | "top" | "bottom" | "left" | "right" | "inline-start" | "inline-end" | "top" |
Which side of the anchor to place the tooltip on. Logical sides follow the document direction when used with `dir`. | ||
| withArrow | boolean | false |
Adds an arrow to the Tooltip content | ||
| sideOffset | number | 4 |
Distance between the anchor and the tooltip. | ||
| Prop | Type | Default |
|---|---|---|
| delay | number | 0 |
Delay in milliseconds before the tooltip opens after hover or focus. | ||
See the Base UI Tooltip API reference for root, trigger, and other props.