Skip to content

fix(core): link Banner expand toggle to its content via aria-controls#3719

Open
bhamodi wants to merge 1 commit into
facebook:mainfrom
bhamodi:a11y/banner-expand-controls
Open

fix(core): link Banner expand toggle to its content via aria-controls#3719
bhamodi wants to merge 1 commit into
facebook:mainfrom
bhamodi:a11y/banner-expand-controls

Conversation

@bhamodi

@bhamodi bhamodi commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Banner's expand/collapse toggle exposed aria-expanded but had no aria-controls, and its collapsible content region had no id -- so the disclosure relationship (toggle button ↔ the region it shows/hides) was implicit only. Screen-reader users heard the expanded/collapsed state with no way to associate it with the region being controlled.

This adds a useId()-generated id on the content region and wires aria-controls to it on the toggle button. Because the region is conditionally rendered (mounted only while expanded), aria-controls is set only while the region is mounted, so it never points at a non-existent id. This matches the aria-controls={... ? ... : undefined} pattern already used by the Date inputs (DateInput, DateRangeInput, DateTimeInput) for their conditionally-mounted popovers. Purely additive; no behavior/visual change. Mirrors the sibling fix on Collapsible (#3707).

Changes

  • Banner/Banner.tsx: useId()id on the content region + aria-controls on the toggle button (set only while the region is mounted).

Test plan

  • node_modules/.bin/vitest run --root . packages/core/src/Banner -- 33 pass, including two new tests (both confirmed failing before the fix):
    • links the expand toggle to its content region via aria-controls -- asserts the toggle's aria-controls resolves via document.getElementById to the region containing the banner children.
    • sets aria-controls only while the content region is mounted -- asserts there is no aria-controls while collapsed (region unmounted, no dangling reference), and that it resolves to the mounted region after expanding.
  • node_modules/.bin/tsc --project packages/core/tsconfig.json --noEmit -- clean.
  • node_modules/.bin/eslint on changed files -- clean.

Notes

Found during a broader a11y audit of core components. Scoped to one fix per PR. Button forwards arbitrary aria-* props to the underlying <button> (the same spread the existing aria-expanded relies on), so aria-controls reaches the DOM. Skipped role="region"/aria-labelledby to keep the change minimal and consistent with #3707.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

@bhamodi is attempting to deploy a commit to the Meta Open Source Team on Vercel.

A member of the Team first needs to authorize it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant