Tooltip
A short hint that appears while the pointer rests on an element or keyboard focus reaches it. Use it to name an icon button or add one line of context, and keep anything the reader must see on the page itself.
Installation
npx @smicolon/fasla-ui@latest add tooltipRun init once per project before adding components. See Installation.
Tooltip is built on Base UI, so it needs the @base-ui/react package, and its avatar slot uses avatar. add installs both with the component, and so does the shadcn CLI.
Preview
Hover over the button, or move to it with Tab.
Variants
Six styles, set with variant. primary, the default, suits everyday labels, and secondary is a quieter neutral. info, success, warning and destructive carry the status colours: pick the one that matches what the message means, and make the words clear on their own. radius chooses between 8px corners for standard and 16px for rounded, which reads as a pill on a single line.
primarysecondaryinfosuccesswarningdestructiveprimary · roundedsecondary · roundedinfo · roundedsuccess · roundedwarning · roundeddestructive · roundedPlacement
side picks the side of the trigger the tooltip sits on, and the arrow points back at it. top, bottom, left and right are fixed sides of the screen, so left stays put on a right-to-left page. inline-start and inline-end mean the start and end of the line, so they swap sides in Arabic. When there is no room, the tooltip flips to the opposite side. Set arrow to false to drop the arrow.
topbottomleftrightinline-startinline-endarrow={false}Content
The text you put inside is the title. description adds a second, less prominent line. icon puts a 16px glyph before the text, in the text colour, and avatar puts a round 12px avatar in the same place, to show who the hint is about. The text wraps at 296px, so a tooltip is at most 320px wide, or 340px with an icon.
descriptioniconavatar296pxAccessibility
- A tooltip is a visual hint: Base UI gives it no role and does not link it to the trigger. Give the trigger its own accessible name, as visible text or an
aria-label, and keep essential information out of the tooltip. - It opens as soon as the pointer rests on the trigger or keyboard focus reaches it, and closes when either leaves or when you press Escape.
- Keep links and buttons out of a tooltip. It closes as focus moves, so nobody can reach them.
- The status styles add colour, not meaning. Say what kind of message it is in the words, or add an icon that does.
- The tooltip takes its direction, language and font from the trigger, even though it renders at the end of
body. Direction is never a prop.
Props
Tooltip
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Shows or hides the tooltip, when controlled. |
defaultOpen | boolean | false | Shows the tooltip at first. |
onOpenChange | (open, eventDetails) => void | — | Called when the tooltip opens or closes. |
disabled | boolean | false | Stops the tooltip from opening. |
TooltipTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | — | Replaces the default button with your element, such as a link or a Button. |
delay | number | 0 | How long to wait before opening, in milliseconds. |
TooltipContent
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "info" | "success" | "warning" | "destructive" | "primary" | Colour of the tooltip. |
radius | "standard" | "rounded" | "standard" | 8px corners, or 16px: a pill on one line. |
side | "top" | "bottom" | "left" | "right" | "inline-start" | "inline-end" | "top" | Side of the trigger it sits on. The inline-* sides follow the reading direction. |
align | "start" | "center" | "end" | "center" | Where along that side it lines up with the trigger. |
sideOffset | number | 8 | Distance from the trigger to the tooltip, in px. |
arrow | boolean | true | Shows the arrow. |
description | ReactNode | — | A second line under the title. |
icon | ReactNode | — | A 16px glyph before the text. |
avatar | Omit<AvatarProps, "size"> | — | Props for an Avatar before the text, always at size 12. |
container | HTMLElement | — | The element the tooltip renders into. Defaults to body. |
className | string | — | Extra classes for the tooltip. |
Usage
Basic tooltip
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
export function ShareTooltip() {
return (
<Tooltip>
<TooltipTrigger>Share</TooltipTrigger>
<TooltipContent>Copy link</TooltipContent>
</Tooltip>
)
}Name an icon button
import { Link } from "lucide-react"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
export function CopyLinkButton() {
return (
<Tooltip>
<TooltipTrigger aria-label="Copy link">
<Link aria-hidden="true" />
</TooltipTrigger>
<TooltipContent>Copy link</TooltipContent>
</Tooltip>
)
}Style, description and icon
import { Info } from "lucide-react"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
export function ShareInfoTooltip() {
return (
<Tooltip>
<TooltipTrigger>Share</TooltipTrigger>
<TooltipContent
variant="info"
side="bottom"
icon={<Info />}
description="Anyone with the link can view this file."
>
Copy link
</TooltipContent>
</Tooltip>
)
}With an avatar
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
export function LastEditedTooltip() {
return (
<Tooltip>
<TooltipTrigger>Share</TooltipTrigger>
<TooltipContent
variant="secondary"
avatar={{ src: "/avatars/layla.png", name: "" }}
description="Edited 5 minutes ago"
>
Layla Haddad
</TooltipContent>
</Tooltip>
)
}At the end of the line
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
export function EndSideTooltip() {
return (
<Tooltip>
<TooltipTrigger>Share</TooltipTrigger>
<TooltipContent side="inline-end">Copy link</TooltipContent>
</Tooltip>
)
}