Skip to content

WB-2148 ActionMenu in Classroom: Ensure implicit list markup is avoided - #3173

Draft
khan-actions-bot wants to merge 1 commit into
mainfrom
claude/WB-2148/action-menu-list-markup
Draft

WB-2148 ActionMenu in Classroom: Ensure implicit list markup is avoided#3173
khan-actions-bot wants to merge 1 commit into
mainfrom
claude/WB-2148/action-menu-list-markup

Conversation

@khan-actions-bot

Copy link
Copy Markdown
Contributor

Summary

Accessibility fix for WB-2148. An audit of the Classroom Teacher experience found that the ActionMenu items (e.g. the class links "Algebra1 - Lowe" and "Writing - Lowe") appear as a list but were not using list markup, so screen reader users had difficulty understanding the content was a list (WCAG 1.3.1 – Info and Relationships).

The dropdown menu was rendered as a <div role="menu"> containing bare menuitem elements. This change renders the dropdown using semantic list markup:

  • The dropdown container is now a <ul> element (previously a <div>).
  • Each item is wrapped in a presentational <li> (role="none").
  • The existing menu/menuitem and listbox/option ARIA roles are preserved, so behavior and the menu-button interaction pattern are unchanged. The role="none" on the <li> keeps the widget role's required parent/child relationship intact.

This matches the WAI-ARIA Menu Button links pattern that ActionMenu already follows.

Scope

The change lives in the shared DropdownCore component, so it also improves SingleSelect and MultiSelect (which render a listbox of options) in the same way. The virtualized list path (used only for 125+ items via react-window) is intentionally left unchanged, since react-window manages its own container/item DOM structure; the ARIA roles remain correct there.

Changes

  • dropdown-core.tsx: container rendered as <ul> (non-virtualized case) and each item wrapped in a presentational <li role="none">.
  • Added unit tests in dropdown-core.test.tsx and action-menu.test.tsx verifying the container is a <ul> and items are wrapped in <li>.
  • Documented the semantic list markup in action-menu.accessibility.mdx.
  • Added a changeset (patch for @khanacademy/wonder-blocks-dropdown).

Testing

  • pnpm jest packages/wonder-blocks-dropdown — all tests pass (including new tests).
  • birthday-picker tests (consumer of SingleSelect) pass.
  • Typecheck passes.
  • Lint passes.

Accessibility notes

  • menu / menuitem and listbox / option roles are unchanged, so assistive technology still announces the widget correctly.
  • <li role="none"> is presentational so the menu still owns its menuitem children (and listbox its option children), satisfying aria-required-children.
  • No ARIA/global-attribute conflict on the <li> (only role="none" is applied).

Key: WB-2148

Co-authored by Claude agent for Jira.

Render the dropdown menu/listbox using semantic list markup so items are
exposed as a list to assistive technologies. The DropdownCore container is
now a <ul> element and each item is wrapped in a presentational <li>
(role="none"), which keeps the existing menu/menuitem and listbox/option
ARIA roles intact.

This affects ActionMenu, SingleSelect, and MultiSelect (all of which use
DropdownCore). The virtualized list path is left unchanged since
react-window manages its own container structure.

Key: WB-2148
@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2ca767f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@khanacademy/wonder-blocks-dropdown Patch
@khanacademy/wonder-blocks-birthday-picker Patch
@khanacademy/wonder-blocks-tabs Patch
eslint-plugin-wonder-blocks-demo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@khan-actions-bot
khan-actions-bot requested a review from a team August 11, 2026 14:30
@github-actions

Copy link
Copy Markdown
Contributor

Size Change: +64 B (+0.05%)

Total Size: 131 kB

📦 View Changed
Filename Size Change
packages/wonder-blocks-dropdown/dist/es/index.js 20.5 kB +64 B (+0.31%)
ℹ️ View Unchanged
Filename Size
packages/eslint-plugin-wonder-blocks/dist/es/index.js 7.11 kB
packages/wonder-blocks-accordion/dist/es/index.js 3.02 kB
packages/wonder-blocks-announcer/dist/es/index.js 2.43 kB
packages/wonder-blocks-badge/dist/es/index.js 2.03 kB
packages/wonder-blocks-banner/dist/es/index.js 2.01 kB
packages/wonder-blocks-birthday-picker/dist/es/index.js 1.93 kB
packages/wonder-blocks-breadcrumbs/dist/es/index.js 798 B
packages/wonder-blocks-button/dist/es/index.js 4.28 kB
packages/wonder-blocks-card/dist/es/index.js 1.09 kB
packages/wonder-blocks-cell/dist/es/index.js 2.19 kB
packages/wonder-blocks-clickable/dist/es/index.js 2.61 kB
packages/wonder-blocks-core/dist/es/index.js 2.6 kB
packages/wonder-blocks-data/dist/es/index.js 5.51 kB
packages/wonder-blocks-date-picker/dist/es/index.js 8.06 kB
packages/wonder-blocks-form/dist/es/index.js 6.39 kB
packages/wonder-blocks-grid/dist/es/index.js 1.25 kB
packages/wonder-blocks-icon-button/dist/es/index.js 4.06 kB
packages/wonder-blocks-icon/dist/es/index.js 1.89 kB
packages/wonder-blocks-labeled-field/dist/es/index.js 3.47 kB
packages/wonder-blocks-layout/dist/es/index.js 1.69 kB
packages/wonder-blocks-link/dist/es/index.js 1.54 kB
packages/wonder-blocks-modal/dist/es/index.js 7.36 kB
packages/wonder-blocks-pill/dist/es/index.js 1.32 kB
packages/wonder-blocks-popover/dist/es/index.js 4.41 kB
packages/wonder-blocks-progress-spinner/dist/es/index.js 1.49 kB
packages/wonder-blocks-search-field/dist/es/index.js 1.12 kB
packages/wonder-blocks-styles/dist/es/index.js 464 B
packages/wonder-blocks-switch/dist/es/index.js 1.6 kB
packages/wonder-blocks-tabs/dist/es/index.js 5.62 kB
packages/wonder-blocks-testing-core/dist/es/index.js 4.09 kB
packages/wonder-blocks-testing/dist/es/index.js 978 B
packages/wonder-blocks-theming/dist/es/index.js 384 B
packages/wonder-blocks-timing/dist/es/index.js 1.53 kB
packages/wonder-blocks-tokens/dist/es/index.js 6.5 kB
packages/wonder-blocks-toolbar/dist/es/index.js 906 B
packages/wonder-blocks-tooltip/dist/es/index.js 6.19 kB
packages/wonder-blocks-typography/dist/es/index.js 1.04 kB

compressed-size-action

@github-actions

Copy link
Copy Markdown
Contributor

npm Snapshot: Published

🎉 Good news!! We've packaged up the latest commit from this PR (96eac02) and published all packages with changesets to npm.

You can install the packages in frontend by running:

./dev/tools/deploy_wonder_blocks.js --tag="PR3173"

Packages can also be installed manually by running:

pnpm add @khanacademy/wonder-blocks-<package-name>@PR3173

@github-actions

Copy link
Copy Markdown
Contributor

A new build was pushed to Chromatic! 🚀

https://5e1bf4b385e3fb0020b7073c-roqntvbaay.chromatic.com/

Chromatic results:

Metric Total
Captured snapshots 164
Tests with visual changes 0
Total stories 867
Inherited (not captured) snapshots [TurboSnap] 377
Tests on the build 541

@jandrade
jandrade marked this pull request as draft August 12, 2026 21:32
@jandrade
jandrade removed the request for review from a team August 12, 2026 21:32
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.

2 participants