- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Card
- Checkbox
- Collapsible
- Combobox
- Context Menu
- Date Picker (Lite)
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP (Lite)
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
Add to library
import { Button } from "@/components/ui/button"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"
export function TooltipDemo() {
return (
<Tooltip>
<TooltipTrigger render={<Button variant="outline" />}>
Hover
</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>
)
}Installation
pnpm dlx shadcnui-hono-jsx@latest add tooltipnpx shadcnui-hono-jsx@latest add tooltipyarn dlx shadcnui-hono-jsx@latest add tooltipbunx shadcnui-hono-jsx@latest add tooltipThis component uses a small client script. add installs it into public/shadcn/; serve that directory at /shadcn/ and load the script on pages that use the component (see Client Scripts):
<script type="module" src="/shadcn/hover.js"></script>Usage
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"<Tooltip>
<TooltipTrigger>Hover</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>Composition
Use the following composition to build a Tooltip:
Tooltip
├── TooltipTrigger
└── TooltipContentSide
Use the side prop to change the position of the tooltip.
Add to library
Add to library
Add to library
Add to library
import { Button } from "@/components/ui/button"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"
export function TooltipSides() {
return (
<div class="flex flex-wrap gap-2">
{(["left", "top", "bottom", "right"] as const).map((side) => (
<Tooltip key={side}>
<TooltipTrigger
render={<Button variant="outline" class="w-fit capitalize" />}
>
{side}
</TooltipTrigger>
<TooltipContent side={side}>
<p>Add to library</p>
</TooltipContent>
</Tooltip>
))}
</div>
)
}With Keyboard Shortcut
import { SaveIcon } from "@/components/icons"
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="outline" size="icon-sm" />}>
<SaveIcon />
</TooltipTrigger>
<TooltipContent>
Save Changes <Kbd>S</Kbd>
</TooltipContent>
</Tooltip>
)
}Disabled Button
Show a tooltip on a disabled button by wrapping it with a span.
This feature is currently unavailable
import { Button } from "@/components/ui/button"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"
export function TooltipDisabled() {
return (
<>
<Tooltip>
<TooltipTrigger render={<span class="inline-block w-fit" />}>
<Button variant="outline" disabled>
Disabled
</Button>
</TooltipTrigger>
<TooltipContent>
<p>This feature is currently unavailable</p>
</TooltipContent>
</Tooltip>
</>
)
}RTL
To enable RTL support in shadcn/ui, see the RTL configuration guide.
// This example sets dir and uses useTranslation because this site is not RTL.
// In an RTL app you won't need them; see the RTL guide.
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, t } = useTranslation(translations, "ar")
return (
<div class="grid gap-4">
<div class="flex flex-wrap justify-center gap-2">
{physicalSides.map((side) => (
<Tooltip key={side}>
<TooltipTrigger render={<Button variant="outline" />}>
{t[side]}
</TooltipTrigger>
<TooltipContent side={side} dir={dir}>
{t.content}
</TooltipContent>
</Tooltip>
))}
</div>
<div class="flex flex-wrap justify-center gap-2">
{logicalSides.map((side) => (
<Tooltip key={side}>
<TooltipTrigger render={<Button variant="outline" />}>
{t[side]}
</TooltipTrigger>
<TooltipContent side={side} dir={dir}>
{t.content}
</TooltipContent>
</Tooltip>
))}
</div>
</div>
)
}Notes
- Opening on hover or keyboard focus needs the client script
/shadcn/hover.js(<script type="module" src="/shadcn/hover.js">); without it the tooltip does not open, but the trigger'saria-describedbystill exposes its text. The popup is a native popover placed with CSS anchor positioning. - Unlike Base UI, the popup has
role="tooltip"and describes the trigger. Controlled state (open,onOpenChange) is not supported. - Accepts
classinstead ofclassName. - Upstream documentation: shadcn/ui Tooltip. See also Differences from shadcn/ui.
API Reference
See the Base UI Tooltip documentation.