Tooltip

Names what's under the pointer.

View as Markdown
<Tooltip>  <TooltipTrigger render={<Button variant="outline" />}>Hover</TooltipTrigger>  <TooltipContent>Add to library</TooltipContent></Tooltip>

Installation

$ npx shadcn@latest add @constella/tooltip

Usage

import {  Tooltip,  TooltipContent,  TooltipTrigger,} from "@/components/primitives/tooltip";
<Tooltip>  <TooltipTrigger>Hover</TooltipTrigger>  <TooltipContent>Add to library</TooltipContent></Tooltip>

Composition

TooltipProvider└── Tooltip    ├── TooltipTrigger    └── TooltipContent

Side

Use the side prop on TooltipContent to place the tooltip. Wrap neighbors in a TooltipProvider, so once one is open the next opens at once.

<TooltipProvider>  {["left", "top", "bottom", "right"].map((side) => (    <Tooltip key={side}>      <TooltipTrigger render={<Button variant="outline" />}>        {side}      </TooltipTrigger>      <TooltipContent side={side}>Add to library</TooltipContent>    </Tooltip>  ))}</TooltipProvider>

Disabled Button

A disabled button takes no pointer events, so put the trigger on a wrapper around it.

<Tooltip>  <TooltipTrigger render={<span />}>    <Button disabled variant="outline">      Disabled    </Button>  </TooltipTrigger>  <TooltipContent>This feature is currently unavailable</TooltipContent></Tooltip>

Kbd

Put a Kbd last in the content; the popup tightens its end around it.

<Tooltip>  <TooltipTrigger    aria-label="Save"    render={<Button size="icon-sm" variant="outline" />}  >    <HugeiconsIcon icon={FloppyDiskIcon} />  </TooltipTrigger>  <TooltipContent>    Save Changes <Kbd>S</Kbd>  </TooltipContent></Tooltip>

API Reference

TooltipTrigger opens after 300ms (Base UI's is 600ms); pass delay to change it. TooltipContent renders the portal, positioner and popup; side, align, sideOffset and alignOffset go to the positioner. The parts stay exported for when it doesn't fit. Every styled part takes sx, applied last. For the rest, see Base UI Tooltip.