Skip to content

Move aria-expanded to the side menu toggle (Fixes #999) - #1202

Open
NUAAwqy wants to merge 1 commit into
mozilla:mainfrom
NUAAwqy:fix/999-sidemenu-aria-expanded
Open

NUAAwqy wants to merge 1 commit into
mozilla:mainfrom
NUAAwqy:fix/999-sidemenu-aria-expanded

Conversation

@NUAAwqy

@NUAAwqy NUAAwqy commented Nov 2, 2026

Copy link
Copy Markdown

Description

MzpSideMenu.init() declared aria-expanded on .mzp-c-sidemenu-main — the content the toggle controls — instead of on the controlling element itself. aria-expanded is a state attribute for a control, so the toggle exposed no state at all, and the content node carried a state that did not describe it. On desktop that was actively wrong: the toggle is hidden (display: none above $mq-md) and the content is always expanded, yet the visible content kept aria-expanded="false".

The toggle already has aria-controls pointing at the content id in the template, so no markup change is needed — the attribute just moves to the element it describes, the same way navigation was fixed for #847.

The state is now derived from the mzp-is-active class that the CSS actually uses to show/hide the content, so it cannot desync from the visible state (and a menu that is already expanded when init() runs is reported as expanded).

  • I have documented this change in the design system.
  • I have recorded this change in CHANGELOG.md.

Issue

Fixes #999 — and mirrors the resolution of #847 (the same mistake in .mzp-c-sidemenu vs .mzp-c-navigation-items), which was fixed by declaring aria-expanded on the menu button.

Testing

Observable behavior with the component template from components/sidebar-menu/sidebar-menu.html:

case before after
mobile, collapsed state declared on the content, nothing on the control toggle aria-expanded="false", no attribute on the content
mobile, after opening aria-expanded="true" on the content, control has no state toggle aria-expanded="true", no attribute on the content
after a second click toggles again, but only on the content toggle aria-expanded="false", matches mzp-is-active removal
desktop (mzp-js-toggle is display: none) content stuck at aria-expanded="false" forever while fully visible content has no state attribute; the toggle's state is on a hidden element, so it is not exposed — consistent with the note in navigation.js that display: none elements are not read
markup pre-expanded with mzp-is-active content stamped aria-expanded="false", first click inverted the wrong value toggle starts at true and follows the class

Checks I ran locally:

  • npx eslint . — no problems; npx stylelint "**/*.scss" — clean; npm run test-build — the new tests/unit/sidemenu.js is picked up by the spec glob and bundles successfully.
  • npm test needs Firefox and Chrome, which this machine does not have, so I ran the Jasmine specs headlessly against the webpack test bundle with jasmine-core 7 inside jsdom instead:
    • tests/unit/sidemenu.js on the pristine main commit: 4 passed, 3 failed (Expected true to be false. for the aria-expanded still present on .mzp-c-sidemenu-main; Expected null to be 'false'. / Expected null to be 'true'. for the missing state on the toggle) — i.e. the new specs fail before the change.
    • same specs with the fix: 7 passed, 0 failed.
  • Full suite in the same jsdom environment, for regressions: main = 39 of 55 passing; this branch = 46 of 62 passing. The 8 failures in both runs are the pre-existing ReferenceError: matchMedia is not defined specs in menu.js and the navigation.js sticky block — jsdom has no matchMedia; nothing else changed. CI (xvfb-run npm test) should run these in real browsers.

Docs: added the aria-controls requirement to the Side Menu readme tips, so the markup contract the JS relies on is written down, and a ## Bug Fixes line in CHANGELOG.md.

One judgement call worth a look in review: on desktop the toggle keeps aria-expanded="false" while hidden. navigation.js goes a step further and removes the attribute when the button is not visible (via IntersectionObserver). I kept this change to the reported defect, but I can mirror the navigation behaviour here if you'd prefer the attribute dropped on wide viewports.

This review/fix was AI-assisted (Qoder Desktop); I read the code and verified the results myself, and per AGENTS.md the commit does not list a model as co-author.

`aria-expanded` was declared on `.mzp-c-sidemenu-main`, the content the
toggle controls, so assistive tech was told the menu was collapsed even
when the content was visible - including on desktop, where the toggle is
hidden and the content is always expanded. Declare it on the `.mzp-js-toggle`
element, which the template already links to the content via `aria-controls`,
and derive its state from `mzp-is-active`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sidemenu JS should not add aria-expanded="false" to .mzp-c-sidemenu-main

1 participant