Components · Feedback
Tooltip
BetaA short hint on hover or focus.
- Source
components/ui/tooltip.tsx - shadcn/ui Tooltip
- Figma: not linked yet (Q13)
When to use
- To name an icon-only button: Duplicate workout, Share with client, Delete workout.
- To add a keyboard shortcut or a short hint to a control that already has a visible label.
When not to use
- For information the coach needs to finish a task, such as a field's format or a price: put it on the page as help text. Tooltips don't work on touch screens and disappear.
- For anything interactive, such as links or buttons: use a Popover.
- For a preview of a linked item: use a Hover card.
- On disabled buttons: they don't receive hover or focus. Say why it's disabled next to it instead.
- To repeat a visible label word for word.
Anatomy
Hover or focus a button above to see the parts: the trigger (the control it describes), the content (a short dark label), and the arrow pointing at the trigger. The content renders in a portal on the popover layer.
Variants
There is one style. Choose the side with side; it flips automatically when there isn't room.
| Side | Use for |
|---|---|
top (default) | Most buttons |
bottom | Buttons at the top of the screen, such as the page header |
left / right | Buttons in a vertical toolbar. These are physical sides, so map "end" to the direction yourself |
States
| State | What changes | Token |
|---|---|---|
| Closed | Nothing shows; the trigger has no aria-describedby | none |
| Open (hover or keyboard focus) | Content fades and zooms in next to the trigger | bg-foreground, text-background, z-(--z-popover) |
| Closing | Fades out when the pointer leaves, focus moves or Escape is pressed | none |
The site's TooltipProvider opens tooltips with no delay (delayDuration={0}, as in shadcn). Radix's own default is 700ms before the first tooltip and 300ms to skip the delay between neighbours. There is no motion token for a hover delay yet, so this page doesn't recommend one.
Usage guidelines
- Every icon-only button needs an
aria-label. The tooltip shows that same name to sighted mouse and keyboard users; it doesn't replace it. - One to four words. If it needs a sentence, it belongs on the page.
- Don't put tooltips on every button in a toolbar that already has text labels.
Content guidelines
- Sentence case, no ending punctuation: "Duplicate workout".
- Start with a verb for actions. Name the object when the icon is generic: "Share with client", not "Share".
- Arabic: the same verbal noun the button would use as a label: "نسخ التمرين", "حذف التمرين".
Accessibility
| Key | Does |
|---|---|
| Tab to the trigger | Opens the tooltip |
| Escape | Closes it; focus stays on the trigger |
| Tab away | Closes it |
- The content has
role="tooltip", and the trigger getsaria-describedbypointing at it while it's open. - A screen reader announces "Delete workout, button". Some also read the description, so it may hear the name twice; that's expected when the tooltip repeats the label.
- Tooltips open on keyboard focus as well as hover, and stay open while the pointer moves onto them (WCAG 1.4.13).
- Tooltips don't open on touch. Never rely on one for the only description of a control.
RTL
The content is centered on the trigger, so most tooltips look the same in both directions. side="left" and side="right" are physical: they don't swap in RTL. For a tooltip at the end of a control, use side={dir === "rtl" ? "left" : "right"}, as in the placement example. Arabic text in the content is right-aligned by the preview's dir.
Tokens used
Read from components/ui/tooltip.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.
| Token | Utilities | SuperCoach | Coach |
|---|---|---|---|
| --background | text-background | white | white |
| --foreground | bg-foreground fill-foreground | neutral-950 | neutral-950 |
- Layer
z-(--z-popover) - Radius
rounded-md - Radius
rounded-sm - Type
text-xs
Props
<TooltipProvider>
Also takes every prop of Radix Tooltip.Provider
No props of its own.
<Tooltip>
Also takes every prop of Radix Tooltip.Root
No props of its own.
<TooltipTrigger>
Also takes every prop of Radix Tooltip.Trigger
No props of its own.
<TooltipContent>
Also takes every prop of Radix Tooltip.Content
No props of its own.
Replaces in coach-admin
From the read-only audit of coach-admin: 44 style values, 55 uses.
coach-admin's shared Tooltip component and its .custom-tooltip styles become this component. Slider value bubbles (.el-slider-tooltip) belong to the slider, not here.
Classes and selectors
.tooltip-inner, .custom-tooltip-inner12.custom-tooltip5.tooltip-trigger.scpay-figures__hint2.tooltip-trigger2.tooltip-icon1.custom-tooltip-inner1.tooltip-trigger:focus-visible1.tooltip1
Files
src/reusableComponents/Tooltip/Tooltip.scss57
The inventory lists the first 12 locations of each value, so file counts are a lower bound.