Show a short hint when someone hovers over or focuses a control. If the preferred side would leave the viewport, the tooltip flips to remain visible.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline">Hover</Button> </TooltipTrigger> <TooltipContent>Add to library</TooltipContent> </Tooltip> </TooltipProvider> )}Installation
npx @arctis-sh/@arctis-sh/ui@latest add tooltipWrap your app, or just the section that uses tooltips, with TooltipProvider.
import { TooltipProvider } from "@/components/ui/tooltip"export default function Layout({ children }) { return <TooltipProvider>{children}</TooltipProvider>}Usage
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"<TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline">Hover</Button> </TooltipTrigger> <TooltipContent>Add to library</TooltipContent> </Tooltip></TooltipProvider>Composition
TooltipProvider
└── Tooltip
├── TooltipTrigger
└── TooltipContentBasic
Hover or focus the trigger to open the tooltip.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline">Hover</Button> </TooltipTrigger> <TooltipContent>Add to library</TooltipContent> </Tooltip> </TooltipProvider> )}Side
Choose a preferred side with side. The tooltip picks another if that position would clip off-screen.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <div className="flex flex-wrap items-center gap-2"> <Tooltip side="left"> <TooltipTrigger asChild> <Button variant="outline">Left</Button> </TooltipTrigger> <TooltipContent>Opens on the left</TooltipContent> </Tooltip> <Tooltip side="top"> <TooltipTrigger asChild> <Button variant="outline">Top</Button> </TooltipTrigger> <TooltipContent>Opens on top</TooltipContent> </Tooltip> <Tooltip side="bottom"> <TooltipTrigger asChild> <Button variant="outline">Bottom</Button> </TooltipTrigger> <TooltipContent>Opens below</TooltipContent> </Tooltip> <Tooltip side="right"> <TooltipTrigger asChild> <Button variant="outline">Right</Button> </TooltipTrigger> <TooltipContent>Opens on the right</TooltipContent> </Tooltip> </div> </TooltipProvider> )}Align
Use align to place the tooltip along the left, center, or right of the trigger. The arrow follows the alignment.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <div className="flex flex-wrap items-center gap-2"> <Tooltip side="top" align="left"> <TooltipTrigger asChild> <Button variant="outline">Left</Button> </TooltipTrigger> <TooltipContent>Aligned left</TooltipContent> </Tooltip> <Tooltip side="top" align="center"> <TooltipTrigger asChild> <Button variant="outline">Center</Button> </TooltipTrigger> <TooltipContent>Aligned center</TooltipContent> </Tooltip> <Tooltip side="top" align="right"> <TooltipTrigger asChild> <Button variant="outline">Right</Button> </TooltipTrigger> <TooltipContent>Aligned right</TooltipContent> </Tooltip> </div> </TooltipProvider> )}Shortcut
Add a keyboard shortcut beside the label when it is useful.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline">Save</Button> </TooltipTrigger> <TooltipContent className="flex items-center gap-2"> Save changes <span className="text-background/60">⌘S</span> </TooltipContent> </Tooltip> </TooltipProvider> )}Disabled
Disabled buttons do not fire pointer events. Wrap the button in a span so the tooltip can still open.
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/components/ui/tooltip"export function Example() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <span className="inline-flex"> <Button variant="outline" disabled> Disabled </Button> </span> </TooltipTrigger> <TooltipContent>Unavailable right now</TooltipContent> </Tooltip> </TooltipProvider> )}API Reference
TooltipProvider
Optional. Sets shared delay and keeps only one tooltip open at a time.
| Prop | Type | Default |
|---|---|---|
| delayDuration | number | 200 |
| skipDelayDuration | number | 300 |
| children | ReactNode | — |
<TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline">Hover</Button> </TooltipTrigger> <TooltipContent>Hint</TooltipContent> </Tooltip></TooltipProvider>Tooltip
| Prop | Type | Default |
|---|---|---|
| side | "top" | "bottom" | "left" | "right" | "top" |
| align | "left" | "center" | "right" | "center" |
| sideOffset | number | 4 |
| delayDuration | number | — |
| open | boolean | — |
| defaultOpen | boolean | false |
| onOpenChange | (open: boolean) => void | — |
| children | ReactNode | — |
<Tooltip> <TooltipTrigger asChild> <Button variant="outline">Hover</Button> </TooltipTrigger> <TooltipContent>Hint</TooltipContent></Tooltip>TooltipTrigger
| Prop | Type | Default |
|---|---|---|
| asChild | boolean | false |
| className | string | — |
<TooltipTrigger asChild> <Button variant="outline">Hover</Button></TooltipTrigger>TooltipContent
| Prop | Type | Default |
|---|---|---|
| side | "top" | "bottom" | "left" | "right" | — |
| align | "left" | "center" | "right" | — |
| sideOffset | number | — |
| className | string | — |
<TooltipContent>Hint</TooltipContent>