Tooltip
A short label that appears when a control is hovered or focused. Use it to name icon buttons, explain a column, or show a shortcut. Keep the text to one line or two; anything longer belongs in a popover.
Usage
import { Paperclip } from "reicon-react/icons/Paperclip";
import { Button } from "@tulipfarm/sprout/button";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@tulipfarm/sprout/tooltip";
<TooltipProvider>
<Tooltip>
<TooltipTrigger
render={<Button size="icon-sm" variant="ghost" aria-label="Attach files" />}
>
<Paperclip size={16} aria-hidden="true" />
</TooltipTrigger>
<TooltipContent>Attach files from your device</TooltipContent>
</Tooltip>
</TooltipProvider>Pass the control to TooltipTrigger through render. Icon-only triggers still need an aria-label; the tooltip describes the control, it doesn’t name it. Wrap a toolbar, header row, or whole app in one TooltipProvider so moving between neighbours opens each tooltip straight away.
Composer toolbar
Ghost icon-sm and sm buttons, a select trigger, and a popover trigger can all be tooltip triggers. To combine triggers, nest them:<TooltipTrigger render={<PopoverTrigger render={<Button />} />} />. The send button switches between default and secondary and is disabled while the draft is empty; a disabled button can’t be hovered or focused, so its tooltip stays closed. While a reply is sending, a stop button takes its place.
Composer toolbar
Icon buttons, a labelled skills button, a mode select, and a model picker each explain themselves. One provider makes neighbours open instantly.
Type a message to enable Send.
Column hints
A plain button with an info icon explains a column heading. Long hints wrap at 20rem.
Column hints
A small info button beside a column heading explains the column. The button is named after its column.
App tiles
BrandStack gives every tile a tooltip with the app’s name. Render a BrandTile as the trigger for a single tile.
App tiles
Each overlapping tile names its app on hover. A single tile can be a tooltip trigger too.
- Summarize this week's launches
- Draft replies to unread customer email
- Linear is connected
Collapsed sidebar
SidebarMenuButton takes a tooltip string or an object of TooltipContent props. It shows beside the icon rail only while the sidebar is collapsed; pass hidden in the object to override that. It works on links, on plain buttons with aria-keyshortcuts, and as the render target of a DropdownMenuTrigger.
Collapsed sidebar
SidebarMenuButton tooltip shows the label beside the icon rail and hides while the sidebar is expanded or on mobile.
API
TooltipProvider takes the Base UI provider props delay (0 here), closeDelay, and timeout. A tooltip outside a provider waits 600ms.
Tooltip and TooltipTrigger wrap the Base UI tooltip root and trigger and take their props, including open, defaultOpen, onOpenChange, disabled, delay, closeOnClick, and render.
TooltipContent renders its own portal, positioner, and arrow. It takes side ("top"), align ("center"), sideOffset (4), alignOffset (0), collisionPadding (8), anchor, keepMounted, container, hidden, and every Base UI popup prop. Each part sets a data-slot.
Accessibility
Tooltips open on hover and on keyboard focus, and close on Escape, blur, or pointer leave. While one is showing it has role="tooltip"and the trigger’s aria-describedby points at it, merged with any description the trigger already has. Never put links or buttons in a tooltip; it can’t receive focus.
Tooltips fade and scale in from their side over 120ms, and open instantly when moving between neighbours in a provider. Motion turns off when reduced motion is requested. In forced-colors mode the label and arrow keep a visible border.
Theme tokens
Tooltips use --sprout-surface, --sprout-line, --sprout-text, --sprout-shadow-panel, the control radius, and the extra small text size. They need no brand color, so they look the same with the neutral and TulipFarm themes in light and dark mode.