Open zacowan opened 9 months ago
This seems like a really niche issue 🤔 Do you have a practical example of where this would be relevant?
This seems like a really niche issue 🤔 Do you have a practical example of where this would be relevant?
Using two JavaScript bundles on the same page that are loaded separately is a common pattern for micro-frontends - so a practical example of where this might be useful is in any micro-frontend environment.
But, this is definitely a niche issue 😅
@benoitgrelard this issue is currently preventing us from locating a modal by role and its accessible name with testing libraries (e.g. Playwright), since there's another Radix primitive in the page that uses the same id
value.
Bug report
For the current/expected behavior, assume the following:
Current Behavior
Under the described assumptions, each bundle has no knowledge that the other bundle exists. So, when the Radix Dialog primitive gets rendered, each bundle increments its own counter separately from the other bundle. Consider the following two bundles:
If each bundle is loaded onto the same page separately from each other, the
contentId
,titleId
, anddescriptionId
values will beradix-0
,radix-1
, andradix-2
, respectively, for each bundle, resulting in an id collision. This, in turn, breaks the aria-attributes necessary to ensure that the Dialog primitive remains accessible.Expected behavior
To be fair, current behavior could be considered the expected behavior. However, it would be nice to have an option to enable Radix primitives to remain accessible, even if they are from different bundles.
Reproducible example
Unable to reproduce easily in CodeSandbox, as I'm not entirely sure how to execute two separate bundles in a CodeSandbox environment.
Suggested solution
To solve this, I have two initial proposals:
Utilize the Window Object for the Count
This is a more automated solution, and involves changing the implementation of
useId
to something like this:However, I'm not sure if this may result in race conditions between two separate bundles (or even two components being rendered from the same bundle) and the window object.
Provide Explicit Props to Allow for Deterministic Ids
This is a more manual approach and perhaps clutters the minimal API of some of these primitives but is rather simple: add props to the
Root
of primitives that useuseId
to allow for passing adeterministicId
to the underlyinguseId
hook. There are several primitives that useuseId
, but for the Dialog primitive that might look something like this:This has additional benefits beyond just the "we can provide an explicit id and it will work". Providing the option to pass an explicit id will let users use the deterministic ids for selectors in their css classes (albeit this may not be useful for the majority of users).
Additional context
Your environment