shadcn.io is not affiliated with official shadcn/ui
Shadcn Tooltip for React and Tailwind
Display information on hover or focus.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/tooltip.jsonpnpm dlx shadcn@latest add https://kit.dev/r/tooltip.jsonnpx shadcn@latest add https://kit.dev/r/tooltip.jsonyarn shadcn@latest add https://kit.dev/r/tooltip.jsonInstall the following dependencies:
bun add @ark-ui/reactpnpm add @ark-ui/reactnpm install @ark-ui/reactyarn add @ark-ui/reactCopy and paste the following code into your project.
"use client";
import { Portal } from "@ark-ui/react/portal";
import {
Tooltip as ArkTooltip,
useTooltipContext,
} from "@ark-ui/react/tooltip";
import type React from "react";
import { cn } from "@/lib/utils";
export const useTooltip = useTooltipContext;
export const Tooltip = (
props: React.ComponentProps<typeof ArkTooltip.Root>
) => {
const {
positioning = {
placement: "top",
},
lazyMount = true,
unmountOnExit = true,
closeDelay = 100,
openDelay = 0,
...rest
} = props;
return (
<ArkTooltip.Root
closeDelay={closeDelay}
data-slot="tooltip"
lazyMount={lazyMount}
openDelay={openDelay}
positioning={positioning}
unmountOnExit={unmountOnExit}
{...rest}
/>
);
};
export const TooltipTrigger = (
props: React.ComponentProps<typeof ArkTooltip.Trigger>
) => <ArkTooltip.Trigger data-slot="tooltip-trigger" {...props} />;
export const TooltipContent = (
props: React.ComponentProps<typeof ArkTooltip.Content>
) => {
const { className, children, ...rest } = props;
return (
<Portal>
<ArkTooltip.Positioner data-slot="tooltip-positioner">
<ArkTooltip.Content
className={cn(
"z-50 w-fit",
"px-3 py-1.5",
"bg-foreground",
"text-background text-xs",
"rounded-lg shadow-lg/5",
"origin-(--transform-origin) animate-in",
"fade-in-0 zoom-in-[98%]",
"data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-[98%]",
"data-[state=closed]:animate-out",
"data-[placement=bottom]:slide-in-from-top-2",
"data-[placement=left]:slide-in-from-end-2",
"data-[placement=right]:slide-in-from-start-2",
"data-[placement=top]:slide-in-from-bottom-2",
"motion-reduce:animate-none!",
className
)}
data-slot="tooltip-content"
{...rest}
>
<TooltipArrow />
{children}
</ArkTooltip.Content>
</ArkTooltip.Positioner>
</Portal>
);
};
export const TooltipArrow = (
props: React.ComponentProps<typeof ArkTooltip.Arrow>
) => {
const { style, ...rest } = props;
return (
<ArkTooltip.Arrow
data-slot="tooltip-arrow"
style={
{
"--arrow-background": "var(--foreground)",
"--arrow-size": "calc(1.5 * var(--spacing))",
...style,
} as React.CSSProperties
}
{...rest}
>
<ArkTooltip.ArrowTip />
</ArkTooltip.Arrow>
);
};Update the import paths to match your project setup.
Anatomy
Tooltip
├── TooltipTrigger
└── TooltipContentUsage
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from "@/components/ui/tooltip";<Tooltip>
<TooltipTrigger>Hover me</TooltipTrigger>
<TooltipContent>
{/* Content */}
</TooltipContent>
</Tooltip>Tooltip vs Toggle Tooltip
You're viewing Tooltip—a label that shows on hover or focus. Use it when the content is supplementary and non-essential, and you're okay with touch users not having access.
Use Tooltip when
- The trigger has its own purpose and the popup is supplementary.
- The content is non-essential—nice-to-have clarity for sighted mouse/keyboard users.
- You're okay with touch users not seeing it—tooltips only open on hover/focus, not on tap.
- The content is short and non-interactive (no links or buttons inside).
Tooltip behavior
- Hover or focus only — Opens on hover/focus; touch users cannot access it.
- Non-interactive — Keep content short with no links or buttons.
- Supplementary — Best for nice-to-have information, not critical content.
Consider Toggle Tooltip when
- The trigger's primary purpose is to reveal the content.
- The content is essential and should be accessible to touch users and screen readers.
- You need click-to-open so everyone can access it.
- The content may be interactive (links, buttons).
Positioning
Use the positioning prop to change the position of the tooltip.
Examples
With Keyboard Shortcut
Disabled Button
Show a tooltip on a disabled button by wrapping it with a span.
API Reference
Tooltip
Root component that wraps the tooltip. Manages open state and positioning.
| Prop | Type | Default |
|---|---|---|
positioning | PositioningOptions | { placement: "top" } |
openDelay | number | 0 |
closeDelay | number | 100 |
lazyMount | boolean | true |
unmountOnExit | boolean | true |
open | boolean | - |
defaultOpen | boolean | - |
onOpenChange | (details: OpenChangeDetails) => void | - |
disabled | boolean | - |
interactive | boolean | false |
closeOnClick | boolean | true |
closeOnEscape | boolean | true |
closeOnPointerDown | boolean | true |
closeOnScroll | boolean | true |
TooltipTrigger
Element that shows the tooltip on hover or focus. Button by default; use asChild for custom elements.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | - |
TooltipContent
Tooltip content shown in a popover on hover or focus.
| Prop | Type | Default |
|---|---|---|
className | string | - |
asChild | boolean | - |
TooltipArrow
Optional arrow pointing to the trigger. Place inside TooltipContent.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | - |
| Attribute | Default |
|---|---|
--arrow-background | var(--foreground) |
--arrow-size | calc(1.5 * var(--spacing)) |
For a complete list of props, see the Ark UI documentation.