Duplicate ARIA id attributes generated by Menu/rc-menu break accessibility – e.g. rc-menu-uuid-✱-/admin-popup
#53,707 创建于 2025年4月30日
描述
Reproduction link
https://github.com/ant-design/ant-design/issues/53706
Steps to reproduce
Capturing the duplicate-ID accessibility errors in Microsoft Edge DevTools
-
Open the page
Start Microsoft Edge and navigate tohttp://localhost:3000/. -
Launch DevTools
- Press F12 (or ⌥ ⌘ I on macOS) – or right-click anywhere on the page and choose Inspect.
-
Open the Issues panel
- In the DevTools toolbar, click the “crossed-arrow in a circle” icon.
If you don’t see it:- Click the ⋯ kebab menu » More tools » Issues.
- In the DevTools toolbar, click the “crossed-arrow in a circle” icon.
-
Make sure third-party issues are shown
- Check Include third-party issues at the top of the panel (Edge keeps the same checkbox Chrome has).
-
Filter to Accessibility issues (optional)
- Expand ▼ Accessibility in the left column to hide Security/Performance noise.
-
Locate the duplicate-ID errors
- You should see one row per repeated
id, e.g.IDs used in ARIA and labels must be unique rc-menu-uuid-81066-1-/admin-popup - Click a row to expand it.
Edge will display:- The offending element (
<ul class="ant-menu …" id="rc-menu-uuid-…">) - Links to Elements (to inspect it in the DOM)
- The request URL (
http://localhost:3000/) - Further reading links to Deque University & webhint.io.
- The offending element (
- You should see one row per repeated
-
Jump to the element in the DOM tree (for screenshots or live edits)
- Click Open in Elements inside the expanded issue.
- The corresponding
<ul>is auto-selected so you can verify the duplicatedid.
-
Copy the issue detail for your report
- Right-click the issue row → Copy issue link (Edge copies a JSON blob you can prettify), or
- Use Copy as HTML in the Elements panel to grab the offending markup.
-
(Optional) Re-run an automated audit
- Still inside DevTools: Lighthouse tab » Accessibility → Generate Report.
You’ll get the same “IDs used in ARIA and labels must be unique” failure with the duplicatedrc-menu-uuid-…ids.
- Still inside DevTools: Lighthouse tab » Accessibility → Generate Report.
Tip: Edge DevTools are Chromium-based, so every step here is identical to Chrome; screenshots from one browser match the layout in the other.
What is expected?
-
One-to-one mapping between trigger and popup
Every<SubMenu>or<Menu.Item>that renders a pop-up must be assigned its ownid(rc-menu-uuid-<seed>-<uniqueIndex>-/<key>-popup).
The corresponding trigger element should reference that id viaaria-controls,aria-owns, oraria-labelledby, so assistive technology can establish a clear relationship. -
No id collisions anywhere in the document
The generated id must be globally unique across the entire DOM tree (not just inside the menu component) to satisfy HTML §4.10.1 and WCAG 2.1 SC 4.1.1 “Parsing”. -
Consistent id format across renders
The id pattern should stay deterministic (same key ⇒ same id) between mounts to prevent unnecessary React reconciliations, but still avoid duplication when multiple copies of the menu exist on one page. -
Zero accessibility audit failures
Running axe-core, Lighthouse Accessibility, or Edge/Chrome Issues panel should produce no “IDs used in ARIA and labels must be unique” errors for menus rendered byantd/rc-menu. -
Screen-reader compatibility
– NVDA Firefox, JAWS Chrome, VoiceOver Safari should announce:
“ – sub-menu, collapsed/expanded” and navigate into the submenu without confusion or focus loss.
– The virtual cursor should encounter each popup exactly once, in the expected order. -
No behavioural regressions
- Keyboard navigation (
← ↑ → ↓,Enter,Space,Esc) continues to work. - Styling and animation of submenu popups remain unchanged.
- Server-side rendering output remains deterministic (important for Next.js / Remix).
- Keyboard navigation (
-
Automated test coverage (internal guideline)
At least one unit test inrc-menuverifies thatuuideventKeycombination yields distinct ids for multipleSubMenus rendered in the same tree.
Meeting all of the above conditions eliminates the accessibility blockers, keeps the public API stable, and aligns antd@5 with WCAG conformance requirements.
What is actually happening?
-
Single-seed UUID reused for every submenu
rc-menucalls its internalgetUuid()helper once when the root<Menu>mounts.
That function returns a “seed” such asrc-menu-uuid-81066.
For each<SubMenu>it then builds the popup id as:<seed>-1-/<eventKey>-popupBecause the seed never changes and the literal string
1is hard-coded, every popup created during the same render pass ends up with the exact same id:rc-menu-uuid-81066-1-/admin-popup rc-menu-uuid-81066-1-/content-popup …
| Environment | Info |
|---|---|
| antd | 5.11.3 |
| React | 18.3.1 |
| System | Mac |
| Browser | MS Edge 135.0.3179.98 |