COMPONENTS / ATOMS / al-tooltip← ALL COMPONENTS

Tooltip

<al-tooltip><ALTooltip> REACTbeta

Reference generated from the custom elements manifest — 6 properties, 3 slots, 2 events.

PLAYGROUND5 CONTROLS
PREVIEW / al-tooltip / SOUTHLEFT
Loading preview
Hover me ⌘ + C Tooltip — ink on paper
position
FLAGS
CODE — HTML / REACT

Guidance

AUTHORED · CITED TO SOURCE

A small floating label attached to a trigger, shown on hover and on focus. It owns the show/hide debounce and the positioning; you give it the control to attach to via the trigger slot and the text via the default slot.

WHEN TO USE

  • A control's meaning is not fully carried by its visible label — most often an icon-only button in a dense toolbar.
  • You are naming something the user can already see, briefly. A tooltip supplements; it does not explain.
  • The trigger is not itself focusable — a plain <span slot="trigger"> — which is the usage the component's own focus handling is written for.

WHEN NOT TO USE

  • The information is required to complete a field. Persistent helper text under the input is read by everyone, including people who never hover.USE INPUT →
  • The content is more than a phrase, or contains its own controls. A tooltip that has to be read is the wrong container for it.USE POPOVER →
  • You are reporting the result of an action.USE TOAST →
  • The content is a decision the user must make before continuing.USE DIALOG →

DO

  • Slot a non-focusable trigger — a <span> or an icon — and let the component supply the tab stop. That is the documented usage, and the case where the description is wired to the element that actually receives focus.
  • Give the trigger control its own accessible name when it IS focusable. Do not let the tooltip be the only place the name exists.
  • Use isDynamic when the tooltip sits near a viewport edge; it repositions based on where the trigger is rather than always honouring position.
  • Set isInteractive only when the tooltip's content genuinely has to be reached with the pointer, and accept that a tooltip you can move into is harder to dismiss.

DON’T

  • Don't put information in a tooltip that exists nowhere else. It is unavailable to touch users, to anyone who does not hover, and — when the trigger is a focusable control — to screen-reader users too.
  • Don't assume aria-describedby reaches your slotted control. The attribute is rendered on the tooltip's own internal trigger wrapper, not on what you slot into it, and the description cannot be projected across the shadow boundary onto a focusable slotted element.
  • Don't slot an <al-button> and expect both a tab stop on the wrapper and the tooltip association. When the slotted trigger has its own focusable element the wrapper deliberately drops its tabindex — it used to produce two tab stops for one control — so the focused control is the button, which carries no reference to the tooltip.
  • Don't use a tooltip on a touch-primary surface as the only affordance. There is no hover there to trigger it.

ACCESSIBILITY IN PRACTICE

  • The tooltip container renders role="tooltip" with a generated id and toggles aria-hidden with its visible state, so it is not announced while hidden.
  • aria-describedby is placed on the internal trigger wrapper. That wrapper is only tabbable when the slotted trigger contains nothing focusable of its own, so the association holds for the plain-<span> case and is lost for the slotted-button case.
  • An empty tooltip is hidden outright — the component measures its container on first update and sets it to display: none below a height threshold — so an empty tooltip fails silently rather than opening blank.
  • Because the tooltip opens on focus as well as hover, a keyboard user reaches it, but only through the tab stop the wrapper provides.

CONTENT GUIDELINES

  • Write a phrase, not a sentence, and do not punctuate it as one. A tooltip is a label.
  • Name the action or the thing — "Duplicate row" — rather than describing the icon or restating what is already visible.
  • Never put the only copy of an instruction, a keyboard shortcut, or an error in a tooltip. Repeat it somewhere permanent.

WHERE THIS CAME FROM

  • libs/al-web-components/components/tooltip/tooltip.tsThe single render site — on the tooltip's own trigger wrapper, not on the slotted control.
  • libs/al-web-components/components/tooltip/tooltip.tsThe recorded fix for the double tab stop: the wrapper is tabbable only when the slotted trigger has nothing focusable of its own.
  • libs/al-web-components/components/tooltip/tooltip.tsThe tooltip role, the generated id it is addressed by, and the `aria-hidden` toggle tied to the visible state.
  • libs/al-web-components/components/tooltip/tooltip.tsThe empty-tooltip guard — the container is hidden when it measures below the height threshold on first update.

Each line above names a file and a literal string that must still appear in it.pnpm gate:guidance re-reads them from this built page, so guidance that has stopped being true fails a check rather than misleading you.

NO DESIGN-SYSTEM PROJECT TRACKS THIS COMPONENT AGAINST A FIGMA FILE — IT IS EITHER OUTSIDE EVERY PROJECT’S DECLARED SCOPE, OR NOT YET SEEDED INTO ITS PROJECT’S PARITY MANIFEST.

CHECKEVIDENCEDETAILRESULT
Default stateAXEtooltip--DefaultPASS
Advanced statesAXE7 further storiesPASS
Screen readerMANUALNo screen-reader pass has been recorded for this component.NOT RECORDED
Keyboard navigationINTERACTION TESTSNo interaction tests and no manual keyboard pass.NOT RECORDED

MEASURED 2026-09-08 · 8 STORIES · AXE WCAG2A + WCAG2AA + WCAG21A + WCAG21AA + WCAG22AA

COLOR CONTRAST0 RULES FAILING

The CI gate disables color-contrast globally (libs/al-web-components/story-fixture/src/main.ts), so its result never reaches a test run. It is enabled for this measurement, and reported here whichever way it comes out.

NO CONTRAST VIOLATIONS ACROSS THIS COMPONENT’S 8 STORIES.

import '@southleft/al-web-components/components/tooltip';
import { ALTooltip } from '@southleft/al-react';
PROPTYPEDEFAULT
hasArrowbooleanDisplays the arrow on the tooltip containertrue
position'top' | 'bottom' | 'left' | 'right'Positions the dropdown tooltip absolutely to the trigger. - **default** places the tooltip to the top - **top** places the tooltip to the top - **bottom** places the tooltip to the bottom - **left** places the tooltip to the left - **right** places the tooltip to the right'top'
isActivebooleanIs active? - **true** Shows the tooltip container - **false** Hides the tooltip container
isDynamicbooleanIs dynamic? - **true** Dynamically position the tooltip container based on it's position in the viewport - **false** Positions the tooltip container based on the position property
isInteractivebooleanIs interactive? - **true** Tooltip container is visible on click and not hover/focus - **false** Tooltip container is visible on hover/focus
ariaDescribedBystringAria Described By attribute - Dynamically set for A11y
SLOTDESCRIPTION
(default)The content that appears inside the tooltip
prefixThe content that appears before the main content
triggerThe trigger that opens the tooltip
EVENTDESCRIPTIONTYPE
onTooltipOpenFired when the tooltip becomes visible. Detail: `{ active }`.CustomEvent
onTooltipCloseFired when the tooltip hides. Detail: `{ active }`.CustomEvent
METHODDESCRIPTION
setDynamicPosition()Handle all dynamic placement
handleOnClickOutside()Handles the click event outside the component: 1. Check if the tooltip is active 2. Determine if the click occurred inside the active tooltip 3. Check if the click occurred outside the active tooltip 4. Close the tooltip if the click occurred outside it
handleOnKeydown()Handle on keydown events 1. If the tooltip is open and escape or tab is keyed, close the tooltip and return focus to the trigger 2. If the enter or spacebar is keyed, toggle the tooltip open or close
handleOnMouseOver()Handle on mouse over events 1. If the toolip is interactive, ignore the mouse handler active state
handleOnMouseOut()Handle on mouse out events 1. If the toolip is interactive, ignore the mouse handler active state
handleOnFocus()Handle on focus events 1. If the toolip is interactive, ignore the focus handler active state
toggleActive()Set tooltip active state 1. Toggle the active state between true and false 2. Open/close the tooltip container based on isActive
open()Open tooltip 1. Set isActive to true to show the tooltip 2. Set the dynamic positioning 3. Dispatch a custom event on open
close()Close tooltip 1. Set isActive to false to hide the tooltip 2. Dispatch a custom event on close

SOURCE — components/tooltip/tooltip.ts · Atoms/Tooltip