Open Bug 2033910 Opened 3 months ago Updated 8 hours ago

App menu badge reasons should be exposed to assistive technology

Categories

(Firefox :: Toolbars and Customization, defect)

Desktop
All
defect

Tracking

()

ASSIGNED
Accessibility Severity s2

People

(Reporter: ayeddi, Assigned: mconley, NeedInfo)

References

Details

(Keywords: access)

Attachments

(2 files)

Steps to reproduce (STR):

  1. Run a screen reader, i.e. NVDA on Windows.
  2. Have badge shown for the app menu, i.e. an update pending on Nightly (orange triangle).
  3. Using keyboard, navigate to the toolbarbutton for Nightly that opens the app menu and observe the screen reader's announcement.

Expected results:

  • The orange triangular badge is indicating there are notifications available (or other meaning of the badge) - it should be explicitly included in the accessible name or in the description of the control.
    • Example announcement: Nightly - notifications available, Open application menu

Actual results:

  • There is no indication of the orange triangular badge or its meaning. The control announces only its name (i.e. Nightly) and title/tooltip text as a description (Open application menu), omitting critical information about the badge.

User impact:

  • Screen reader users or those relying on assistive technologies (i.e. users with visual disabilities, cognitive disabilities, and others) won't have access to crucial information about the purpose of the badge, making it hidden from any user of assistive technology. The omission leads to confusion and missed functionality for users who can't perceive visual indicators and for general user population too.
  • Users with anxiety would likely avoid trying to activate this control to try it observe what it could do and this is likely contribute to the increased anxiety around use of the Firefox interface.

Recommendation:

  1. Include the badge indication in the accessible name of the control, for instance by appending notifications available explicitly at the end of the button's name or at the start of the tooltip text (accessible description)
    • Ensure screen reader announcements clearly convey actionable meaning, consistent with visual indicators shown to sighted users.

The severity field is not set for this bug.
:Gijs, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(gijskruitbosch+bugs)

(In reply to Anna Yeddi [:ayeddi] from comment #0)

  1. Include the badge indication in the accessible name of the control, for instance by appending notifications available explicitly at the end of the button's name or at the start of the tooltip text (accessible description)
    • Ensure screen reader announcements clearly convey actionable meaning, consistent with visual indicators shown to sighted users.

I am confused by this recommendation because "notifications available" doesn't feel like "actionable meaning" to me.

There are different badges that can appear here (but only ever 1 at a time). Is it really enough just to indicate "there is a notification available"? (edit: to make it more explicit: should it not include the messaging in the notification or at least the general subject, e.g. app update, extension update, account issues, etc.?)

Severity: -- → S2
Flags: needinfo?(gijskruitbosch+bugs) → needinfo?(ayeddi)
OS: Unspecified → All
Hardware: Unspecified → Desktop
Summary: App menu includes a triangle badge that is not exposed to assistive technology → App menu badge reasons should be exposed to assistive technology

(In reply to :Gijs (he/him) from comment #2)

(In reply to Anna Yeddi [:ayeddi] from comment #0)

  1. Include the badge indication in the accessible name of the control, for instance by appending notifications available explicitly at the end of the button's name or at the start of the tooltip text (accessible description)
    • Ensure screen reader announcements clearly convey actionable meaning, consistent with visual indicators shown to sighted users.

I am confused by this recommendation because "notifications available" doesn't feel like "actionable meaning" to me.

There are different badges that can appear here (but only ever 1 at a time). Is it really enough just to indicate "there is a notification available"? (edit: to make it more explicit: should it not include the messaging in the notification or at least the general subject, e.g. app update, extension update, account issues, etc.?)

This is a valid concern, but I cannot address it because I do not know what this and other badges mean. Ideally, the meaning of the badge would be included in the accessible name of the control or even in the tooltip, so all users have clarity.

For instance, the green dot (I assume) means that there is an update available for my Firefox. Firefox application menu (update available) would be a great textual indicator of this essential graphic. Actionable meaning would be: there is something that needs your attention - or similar.

Flags: needinfo?(ayeddi)

Triage / proposed fix plan (code inspection only, not verified by running):

Root cause. The app-menu button badge is purely visual. PanelUI._showBadge() (browser/components/customizableui/content/panelUI.js, ~line 1194) only does this.menuButton.setAttribute("badge-status", notification.id), and the icon is drawn entirely in CSS (browser/themes/shared/customizableui/panelUI-shared.css and .../toolbarbutton-icons.css). The button's accessible name/description come solely from appmenu-menu-button-closed2/-opened2 in browser/locales/en-US/browser/appmenu.ftl ({ -brand-short-name } + "Open application menu"), so no badge meaning is exposed to AT. _clearBadge() only removes the attribute.

Re Gijs's question (comment 2/3): there are several distinct badge states (never >1 at once). The known badge-status values are update-available, update-downloading, update-manual, update-other-instance, update-restart, update-unsupported, addon-alert, fxa-needs-authentication (plus extension-new-tab/download-success, whose badge is visually hidden). So the accessible text should be per-status, not a generic "notification available."

Proposed fix.

  1. Add one descriptive Fluent string per meaningful badge-status in appmenu.ftl (wording can mirror the existing appmenuitem-banner-update-* strings, e.g. "Update available", "Restart to finish update", "Attention required", etc.).
  2. In _showBadge(notification), map notification.id → the matching Fluent id and set it as an accessible description on #PanelUI-menu-button (e.g. document.l10n.setAttributes targeting an aria-description), keeping the brand name as the accessible name. Use a dedicated attribute rather than .tooltiptext/.label, because _updatePanelButton() rewrites those on every open/close and would clobber it.
  3. Clear it in _clearBadge().

Keep the change scoped to the app-menu button; the sibling fxa-toolbar button (badge-status="login_failed", handled in browser/base/content/browser-sync.js) has the same gap and could get the same treatment in a follow-up.

Tests (verification anchor): browser/components/customizableui/test/browser_panelUINotifications.js exercises badge show/clear and is the place to assert the new accessible text; browser/base/content/test/sync/browser_fxa_badge.js covers the related fxa badge.

Note: exact ARIA mechanism (aria-description vs. appending to the name) is a call best confirmed by a11y review.

This is an automated analysis result. If this result is incorrect please add a needinfo and feel free to correct the error.

I used Hackbot's frontend-triage skill to try to summarize a way forward here, which sounds reasonable - an aria-description added to the node for each badge state that clearly describes what the badge is trying to draw attention for.

Submitted a patch implementing the agreed approach (comment #5): D-patch.

  • Adds an aria-description to #PanelUI-menu-button, set per badge-status in _showBadge() and cleared in _clearBadge(), so screen readers announce what the badge means (e.g. "Update available", "Restart to finish updating", "Add-ons need your attention", "Sign back in to your account").
  • Covers only the states that render a visible badge (the update-* states, addon-alert, fxa-needs-authentication); update-succeeded/-failed/extension-new-tab/download-success show no visible badge and get no description.
  • One descriptive Fluent string per state in appmenu.ftlwording should be confirmed by a11y review.

Two caveats:

  1. Because aria-description takes precedence over the tooltiptext, while a badge is present the button's accessible description becomes the badge meaning instead of "Open application menu" (its name/role still convey it opens the app menu). If keeping both is preferred, say so and I'll fold the action into the name instead.
  2. The regression test added to browser_panelUINotifications.js could not be executed in the automated environment (no browser-chrome mochitest runner available here); it needs a normal mach test run.

The sibling fxa-toolbar button (badge-status="login_failed", handled in browser-sync.js) has the same gap; left as a follow-up.

This is an automated analysis result. If this result is incorrect please add a needinfo and feel free to correct the error.

Trying the bug-fix skill just to see what it produces. Hopefully it's useful.

The app menu button badge is purely visual: PanelUI._showBadge() only sets the badge-status attribute and the icon is drawn in CSS, so screen readers get no indication of what the badge means.

This adds an aria-description to #PanelUI-menu-button describing the badge for each badge-status that renders a visible badge (the update-* states, addon-alert, fxa-needs-authentication). One descriptive Fluent string is added per state in appmenu.ftl. The description is set in _showBadge() and removed in _clearBadge().

It is kept as a plain attribute (set via document.l10n.formatValue) rather than on the button's label/tooltiptext, because _updatePanelButton() rewrites those on every open/close and would clobber it. Statuses that do not render a visible badge (e.g. update-succeeded, extension-new-tab) are intentionally omitted so we never expose a description without a matching visual. A race guard re-checks the current badge-status after the async translation.

Verified against the accessibility engine that aria-description on the XUL button is exposed as the accessible description (LocalAccessible::Description -> ARIADescription -> nsAccUtils::GetARIAAttr). Adds a regression test to browser_panelUINotifications.js.

The sibling fxa-toolbar button (badge-status="login_failed") has the same gap and can get the same treatment in a follow-up.

Note: exact wording of the strings should be confirmed by a11y review.

Assignee: nobody → mconley
Status: NEW → ASSIGNED

Hey bolsson, a localization question here. The guidance in comment 3 is to append a string contained in parentheses to the end of the button label, so that it ultimately has the formula: "<Name of button> (<description of badge action>)"

How universal is the ordering here, localization-wise? Can I assume the above formula (name prior to description) is not appropriate in all locales for an aria description?

If so, does it make sense to have a bunch of strings here for each badge state that are a little redundant, like:

appmenu-menu-button-badge-update-available = { -brand-short-name } application menu (update available)
appmenu-menu-button-badge-addon-alert = { -brand-short-name } application menu (add-ons need your attention)

?

Flags: needinfo?(bolsson)

Here's an example of a string doing something similar:
https://transvision.flod.org/string/?entity=browser/browser/contextual-manager.ftl:contextual-manager-username-login-line-with-alert.aria-label&repo=gecko_strings

In general it follows at the relative direction of the "end" of the string (depending on if it's LTR or RTL).

I'm a little fuzzy on the scope here - does this apply to only the single button { -brand-short-name } application menu, or are we also talking about multiple buttons?

If we're solving for just the one button, then localization scope would the same and it would be safer to localize the whole string rather than try to assemble it out of separate strings at runtime.

Flags: needinfo?(bolsson)
Flags: needinfo?(mconley)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: