Overlays
Tooltip
A short, high contrast label that appears on hover or focus, mostly for icon buttons and keyboard shortcuts.
npx prodular-ui add tooltipToolbar with shortcuts
Kbd inside a tooltip adapts to the dark surface.
import { BoldIcon, CodeIcon, ItalicIcon, LinkIcon, ListIcon } from "lucide-react"
import { Button } from "@/components/ui/button"import { Kbd, KbdGroup } from "@/components/ui/kbd"import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
const tools = [ { label: "Bold", icon: BoldIcon, keys: ["⌘", "B"] }, { label: "Italic", icon: ItalicIcon, keys: ["⌘", "I"] }, { label: "Inline code", icon: CodeIcon, keys: ["⌘", "E"] }, { label: "Add link", icon: LinkIcon, keys: ["⌘", "K"] }, { label: "Bulleted list", icon: ListIcon, keys: ["⌘", "⇧", "8"] },]
export default function TooltipToolbar() { return ( <div className="flex items-center gap-0.5 rounded-lg border bg-card p-1 shadow-xs"> {tools.map((t) => ( <Tooltip key={t.label}> <TooltipTrigger render={<Button variant="ghost" size="icon-sm" aria-label={t.label} />}> <t.icon /> </TooltipTrigger> <TooltipContent> {t.label} <KbdGroup> {t.keys.map((k) => ( <Kbd key={k}>{k}</Kbd> ))} </KbdGroup> </TooltipContent> </Tooltip> ))} </div> )}Sides
import { Button } from "@/components/ui/button"import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
const sides = ["top", "right", "bottom", "left"] as const
export default function TooltipSides() { return ( <div className="flex flex-wrap items-center justify-center gap-3"> {sides.map((side) => ( <Tooltip key={side}> <TooltipTrigger render={<Button variant="outline" className="capitalize" />}>{side}</TooltipTrigger> <TooltipContent side={side}>Synced 2 minutes ago</TooltipContent> </Tooltip> ))} </div> )}Anatomy
<Tooltip> <TooltipTrigger render={<Button variant="ghost" size="icon-sm" aria-label="Bold" />}> <BoldIcon /> </TooltipTrigger> <TooltipContent> Bold <KbdGroup><Kbd>⌘</Kbd><Kbd>B</Kbd></KbdGroup> </TooltipContent></Tooltip>Guidance
Use it when
- Use on every icon only button to name it, and to teach keyboard shortcuts.
- Keep the text to a few words. Sentence case, no full stop.
Avoid
- Essential information or anything interactive. Tooltips do not open on touch and cannot hold links.
- Repeating the visible label of a text button.
Rules for AI agents
Published in llms-full.txt and the registry, so coding agents follow them when they build with this component.
- Wrap the app once in TooltipProvider. It is already in the root layout of the docs.
- Use TooltipTrigger render={<Button size="icon" aria-label="..." />}. The aria-label is still required, the tooltip is not a label for screen readers.
- Add shortcuts with Kbd or KbdGroup after the text. Do not style them yourself.
- Pass showArrow={false} only when the tooltip sits flush against a toolbar edge.
- Use variant="surface" for readouts over maps, charts and dark canvases.
- For points without a DOM element, pass anchor={pointAnchor(x, y, container)} from @/components/ui/point-anchor and control open, instead of positioning a div yourself.
API
TooltipContent
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "top" | Preferred side. |
| showArrow | boolean | true | Draws an arrow pointing at the trigger. |
| sideOffset | number | 6 | Gap to the trigger in px. |
| variant | "default" | "surface" | "default" | default is the inverted label; surface uses the popover surface, for dark and dense screens and readouts. |
| anchor | Element | VirtualAnchor | RefObject | Positions against something other than the trigger: pointAnchor() for map markers and chart points. |
TooltipProvider
| Prop | Type | Default | Description |
|---|---|---|---|
| delay | number | 0 | Shared open delay in ms for every tooltip inside. |