ant-design/ant-design

Duplicate ARIA id attributes generated by Menu/rc-menu break accessibility – e.g. rc-menu-uuid-✱-/admin-popup

Open

#53,707 创建于 2025年4月30日

在 GitHub 查看
 (3 评论) (1 反应) (0 负责人)TypeScript (98,031 star) (54,612 fork)batch import
Inactivehelp wanted⌨️ Accessibility

描述

Reproduction link

https://github.com/ant-design/ant-design/issues/53706

Steps to reproduce

Capturing the duplicate-ID accessibility errors in Microsoft Edge DevTools

  1. Open the page
    Start Microsoft Edge and navigate to http://localhost:3000/.

  2. Launch DevTools

    • Press F12 (or ⌥ ⌘ I on macOS) – or right-click anywhere on the page and choose Inspect.
  3. 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.
  4. 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).
  5. Filter to Accessibility issues (optional)

    • Expand ▼ Accessibility in the left column to hide Security/Performance noise.
  6. 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.
  7. 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 duplicated id.
  8. 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.
  9. (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 duplicated rc-menu-uuid-… ids.

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 own id (rc-menu-uuid-<seed>-<uniqueIndex>-/<key>-popup).
    The corresponding trigger element should reference that id via aria-controls, aria-owns, or aria-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 by antd/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).
  • Automated test coverage (internal guideline)
    At least one unit test in rc-menu verifies that uuid eventKey combination yields distinct ids for multiple SubMenus 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-menu calls its internal getUuid() helper once when the root <Menu> mounts.
    That function returns a “seed” such as rc-menu-uuid-81066.
    For each <SubMenu> it then builds the popup id as:

    <seed>-1-/<eventKey>-popup
    

    Because the seed never changes and the literal string 1 is 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

贡献者指南