Tooltip is never announced, cannot be dismissed, cannot be hovered, and forces its content onto one line — adopting it is a downgrade from a native title.
All four are visible in src/ui/tooltip/Tooltip.stx as it stands on 0.2.382.
1. The tooltip is never announced (the significant one)
<div :show="isVisible() && !" class="" role="tooltip">role="tooltip" does nothing on its own. A tooltip reaches a screen reader only when the trigger references it, via aria-describedby pointing at the tooltip's id. Nothing here generates an id for the tooltip or puts aria-describedby on the slotted trigger, so the text is unreachable.
A native title attribute is announced. So for a screen-reader user, replacing title="…" with <Tooltip> removes information that was previously available.
2. Not dismissible (WCAG 2.1 SC 1.4.13)
There is no Escape handling. 1.4.13 requires that content shown on hover or focus can be dismissed without moving the pointer or focus.
3. Not hoverable (same SC)
pointer-events-noneis in tooltipClasses. The pointer cannot enter the tooltip, so a user who moves toward it to read it dismisses it. 1.4.13 requires the content stay visible while the pointer is over it — which matters most for exactly the long tooltips that are hardest to read quickly.
4. whitespace-nowrap forces one line
Also in tooltipClasses. Our tooltips are full sentences, e.g. "The invite email was not delivered — the address was rejected by the receiving server." On a 390px viewport that renders as a single line several times the viewport width. We have a visual gate that fails on horizontal overflow, and this is precisely what it catches.
Suggested fix
- Give the tooltip panel
id="tooltip-${$uid}"and setaria-describedbyto it on the trigger wrapper, so the relationship exists whether the tooltip is open or not. - Bind Escape on the wrapper to
hideTooltip(). - Drop
pointer-events-noneand add@mouseenter/@mouseleaveon the panel so moving onto it keeps it open. - Replace
whitespace-nowrapwith amax-w-*and normal wrapping, or make nowrap an opt-in prop.
Note on the focus path
@focusin/@focusout on the wrapper is the right idea, but it only fires when the slotted trigger is focusable. A tooltip on a non-interactive <span> — the common case in our markup — still never opens by keyboard. Worth documenting that the trigger must be focusable, or giving the wrapper tabindex="0" when the slot contains nothing focusable.
Found on @stacksjs/components 0.2.382. Context: 119 title= attributes across six apps were the intended migration target, so this one blocks real adoption. Related: #2043 (form controls), #2044 (Badge).