Skip to content

Tooltip aria-describedby not announced for navigation buttons #849

@swashbuck

Description

@swashbuck

Subject

Navigation buttons with tooltips (Dev Tools, Page Level Progress, ToC, Home Button, etc.) have aria-describedby set pointing to the tooltip element, but screen readers never announce the tooltip text.

Root cause

In TooltipItemView line 134, ariaHidden is computed as:

ariaHidden: (document.activeElement === this.$target[0] || this.isStatic)

When a button has keyboard focus, ariaHidden is true, and tooltip.jsx applies aria-hidden="true" to .tooltip__body. The tooltip text is invisible to screen readers at exactly the moment it is needed, and aria-describedby points to a hidden subtree which screen readers ignore. The aria-live="assertive" region also fires nothing as the inserted content is aria-hidden.

Context

Navigation buttons already have aria-label providing their accessible name. Tooltips on these buttons are a visual affordance for sighted users when button labels are hidden — screen reader users don't need the tooltip text, they get the name from aria-label. The other known uses of the tooltip system are adapt-pageNav (Previous, Next, Home buttons — also navigation buttons with aria-label) and adapt-contrib-hotgraphic, which uses static tooltips — these currently have aria-hidden="true" applied via the isStatic condition.

Based on the above, it is unclear whether any current tooltip use relies on aria-describedby being readable by screen readers. However, the fix should still be opt-in rather than removing aria-describedby globally, to avoid breaking any future tooltip uses that may legitimately rely on it.

Suggested fix

Add an opt-out flag to tooltips.register():

tooltips.register({
  _id: 'devtools',
  _setAriaDescribedBy: false,
  ...
});

TooltipItemView.initialize() would then conditionally skip setting aria-describedby based on that flag. Nav buttons opt out; other tooltip targets retain the current behaviour.

Also note: there is a stale-attribute bug in TooltipItemView.remove() where this.$target is nulled before the removeAttr check, so aria-describedby is never cleaned up on the button after the tooltip is destroyed regardless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status

    New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions