Skip to content

Find what you need, instantly

Search components, ARIA roles & attributes, and WCAG criteria.

Overlays

Tooltip

A supplementary popup showing extra info on hover or focus.

Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-02.

Implementation

Shows on hover AND focus, role="tooltip" with aria-describedby, Escape to dismiss, and a brief hover-delay so the pointer can reach the tooltip itself.

tooltip-pattern.tsx
function TooltipPattern({ label, tooltip }) {
  const [visible, setVisible] = useState(false);
  const hideTimeoutRef = useRef(null);
  const tooltipId = useId();

  function show() {
    clearTimeout(hideTimeoutRef.current);
    setVisible(true);
  }
  // Delay gives the pointer time to move from the trigger onto the
  // tooltip itself (SC 1.4.13 "hoverable").
  function scheduleHide() {
    hideTimeoutRef.current = setTimeout(() => setVisible(false), 150);
  }

  return (
    <span style={{ position: "relative" }}>
      <button
        aria-describedby={visible ? tooltipId : undefined}
        onMouseEnter={show}
        onMouseLeave={scheduleHide}
        onFocus={show}     // <- keyboard users MUST get this too
        onBlur={() => setVisible(false)}
        onKeyDown={e => { if (e.key === "Escape") setVisible(false); }}
      >
        {label}
      </button>
      {visible && (
        <span id={tooltipId} role="tooltip" onMouseEnter={show} onMouseLeave={scheduleHide}>
          {tooltip}
        </span>
      )}
    </span>
  );
}

Live demo

Required roles, states & properties

Required roles, states, and properties
ElementAttributeWhy
Tooltip popuprole="tooltip"Identifies the popup as supplementary description text, not an interactive widget or landmark.
Trigger elementaria-describedbyProgrammatically links the trigger to the tooltip's id so a screen reader announces the tooltip text as a description whenever the trigger is focused — this is the whole mechanism; without it the tooltip is invisible to AT even if it's visible on screen.
Tooltip popup contentText only, no interactive childrenA tooltip must not contain links, buttons, or form controls. Content that needs to be interactive belongs in a Popover-style pattern instead.

Keyboard interaction model

Keyboard interaction model
KeyBehavior
Tab (to the trigger)Shows the tooltip — focus alone must trigger it, not just mouse hover.
Shift+Tab / Tab (away)Hides the tooltip as focus leaves the trigger.
Escape (while trigger has focus)Hides the tooltip without moving focus away from the trigger (dismissible, per SC 1.4.13).

Focus management rules

  • The tooltip never receives focus itself — it is purely supplementary to whatever element is already focused.
  • Focusing the trigger shows the tooltip; blurring the trigger hides it.
  • Escape hides the tooltip while leaving focus exactly where it was, on the trigger.
  • A short close delay on mouseleave lets the pointer travel from the trigger onto the tooltip content itself without it disappearing mid-move.

WCAG 2.2 success criteria mapping

WCAG 2.2 success criteria that apply to this component
SCNameLevelWhy it applies
1.4.13Content on Hover or FocusAAContent revealed on hover/focus (e.g. tooltips) is dismissible, hoverable, and persistent.
2.1.1KeyboardAAll functionality is operable through a keyboard interface with no specific timing.
4.1.2Name, Role, ValueAFor all UI components, name, role, and value are programmatically determinable; states and changes are announced.

References