Skip to content

[a11y] Tooltips cannot be dismissed with Escape key #7594

@ggdouglas

Description

@ggdouglas

Summary

Tooltips in Blueprint cannot be dismissed using the Escape key, which violates the WCAG 2.1 Success Criterion 1.4.13 (Content on Hover or Focus). This makes it impossible for users to dismiss tooltip content without moving their pointer or keyboard focus, which is particularly problematic for users with low vision who use screen magnification, users with low pointer accuracy, and keyboard-only users.

WCAG 2.1 Success Criterion 1.4.13

Success Criterion 1.4.13: Content on Hover or Focus states:

Where receiving and then removing pointer hover or keyboard focus triggers additional content to become visible and then hidden, the following are true:

Dismissible: A mechanism is available to dismiss the additional content without moving pointer hover or keyboard focus, unless the additional content communicates an input error or does not obscure or replace other content.

The Escape key is the standard mechanism for dismissing such content.

ARIA Authoring Practices Guide (APG)

The WAI-ARIA Tooltip Pattern explicitly specifies keyboard interaction requirements:

Keyboard Interaction

Escape: Dismisses the Tooltip.

Note:

  1. Focus stays on the triggering element while the tooltip is displayed.
  2. If the tooltip is invoked when the trigger element receives focus, then it is dismissed when it no longer has focus (onBlur).
  3. If the tooltip is invoked when a pointing cursor moves over the trigger element, then it remains open as long as the cursor is over the trigger or the tooltip.

Current Behavior

  1. Hover over a tooltip target to display the tooltip
  2. Press the Escape key
  3. Expected: Tooltip should close
  4. Actual: Tooltip remains open and does not respond to Escape key

Reproduction

Image

Demo of the issue: https://codesandbox.io/p/sandbox/j5cyp6

Root Cause Analysis

Tooltip has the following component hierarchy: <Tooltip><Popover><Overlay2>

autoFocus={false}
canEscapeKeyClose={false}

Both the autoFocus and canEscapeKeyClose props are hardcoded to false in the Popover component rendered by Tooltip.

This contradicts with the inherited prop interface of Tooltip which states that these props should default to true:

If we change canEscapeKeyClose={true}, the escape key still won't work because Overlay2's escape key handler is attached to the container element (onKeyDown={handleContainerKeyDown}). Without autoFocus={true}, escape key events will fire on the document body, not on the Overlay2 container.

const handleContainerKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLElement>) => {
if (e.key === "Escape" && canEscapeKeyClose) {
onClose?.(e);
// prevent other overlays from closing
e.stopPropagation();
// prevent browser-specific escape key behavior (Safari exits fullscreen)
e.preventDefault();
}
},
[canEscapeKeyClose, onClose],
);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions