Skip to content

[docs] Use React.useId() for demo IDs#48300

Merged
mj12albert merged 5 commits intomui:masterfrom
Janpot:fix/demo-useId-aria
Apr 19, 2026
Merged

[docs] Use React.useId() for demo IDs#48300
mj12albert merged 5 commits intomui:masterfrom
Janpot:fix/demo-useId-aria

Conversation

@Janpot
Copy link
Copy Markdown
Member

@Janpot Janpot commented Apr 16, 2026

Summary

Accordion, menu, radio, select, text-field, and slider demos use hardcoded IDs for aria-controls / aria-labelledby / aria-describedby / htmlFor. When users copy these snippets into apps and render multiple instances, duplicate IDs end up in the DOM and break assistive tech.

Switch to React.useId() so each rendered instance gets a unique base ID.

Relates to mui/mui-public#1241

Pattern

Each demo calls React.useId() once per logical control and derives all related IDs from it via template literals — even when the control only exposes a single ID. This keeps the shape of the code identical across demos with one ID and demos with several.

const id = React.useId();

<FormLabel id={`${id}-label`}>Gender</FormLabel>
<RadioGroup aria-labelledby={`${id}-label`}>

The alternative — one useId() per ID role, named by role — was considered and rejected. It reads fine for a single-ID case but demos with multiple related IDs end up with a noisy prologue and no common prefix tying the IDs to the same control:

const labelId = React.useId();
const helperTextId = React.useId();

<InputLabel id={labelId}>Age</InputLabel>
<Select labelId={labelId} aria-describedby={helperTextId}>...</Select>
<FormHelperText id={helperTextId}>...</FormHelperText>

Preview: https://deploy-preview-48300--material-ui.netlify.app/material-ui/react-accordion/

Accordion and menu demos use hardcoded IDs for aria-controls and
aria-labelledby. When the same demo appears multiple times on a page,
this produces duplicate IDs. Switch to React.useId() to generate
unique IDs per instance.
@Janpot Janpot changed the title [docs] Use React.useId() for demo IDs to avoid duplicates [docs] Use React.useId() for demo IDs Apr 16, 2026
@code-infra-dashboard
Copy link
Copy Markdown

code-infra-dashboard bot commented Apr 16, 2026

Bundle size

Bundle Parsed size Gzip size
@mui/material 0B(0.00%) 0B(0.00%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/private-theming 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes

Deploy preview

https://deploy-preview-48300--material-ui.netlify.app/


Check out the code infra dashboard for more information about this PR.

@Janpot Janpot added the docs Improvements or additions to the documentation. label Apr 16, 2026
@Janpot Janpot marked this pull request as ready for review April 16, 2026 11:42
@Janpot Janpot requested a review from a team April 16, 2026 11:42
@oliviertassinari oliviertassinari added accessibility a11y scope: accordion Changes related to the accordion. labels Apr 16, 2026
@oliviertassinari oliviertassinari changed the title [docs] Use React.useId() for demo IDs [accordion][docs] Use React.useId() for demo IDs Apr 16, 2026
@oliviertassinari
Copy link
Copy Markdown
Member

Oh, I thought we already had an issue for this, created #48305.

@mj12albert
Copy link
Copy Markdown
Member

FWIW thse also rely on manual ids https://mui.com/material-ui/react-select/#basic-select

@Janpot
Copy link
Copy Markdown
Member Author

Janpot commented Apr 17, 2026

FWIW these also rely on manual ids https://mui.com/material-ui/react-select/#basic-select

I'lll take a look, I only fixed the ones that were causing duplicate ids in our html.

Janpot added 2 commits April 17, 2026 10:40
…o IDs

Extends the accordion/menu demo fix to the remaining demos that wire
hardcoded strings into aria-labelledby / aria-controls / aria-describedby
or pair an id with htmlFor. Duplicate IDs would be emitted when these
demo snippets are copied into apps and rendered multiple times.
@Janpot Janpot changed the title [accordion][docs] Use React.useId() for demo IDs [docs] Use React.useId() for demo IDs Apr 17, 2026
@Janpot Janpot changed the title [docs] Use React.useId() for demo IDs [docs] Use React.useId() for demo IDs Apr 17, 2026
Copy link
Copy Markdown
Member

@ZeeshanTamboli ZeeshanTamboli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. We should include as much of this as possible by default within the components.

@ZeeshanTamboli ZeeshanTamboli added scope: all components Widespread work has an impact on almost all components. and removed scope: accordion Changes related to the accordion. labels Apr 18, 2026
@mj12albert mj12albert enabled auto-merge (squash) April 19, 2026 09:56
@mj12albert mj12albert merged commit 107f22c into mui:master Apr 19, 2026
23 checks passed
@oliviertassinari
Copy link
Copy Markdown
Member

oliviertassinari commented Apr 19, 2026

We should include as much of this as possible by default within the components.

@ZeeshanTamboli True. Now, migrating all the demos from hard-coded IDs to React.useId() feels like it helps; we can count the number of demos that have a random ID, a clear measure for progress.


I don't know if this makes the demos more portable, though. There are conflicting forces:

  1. It's a pain to copy the snippet and add the ID generator at the top of the component.
  2. It's more accurate in practice with unique IDs.
  3. AI can solve 1. to a good extent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility a11y docs Improvements or additions to the documentation. scope: all components Widespread work has an impact on almost all components.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants