-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[material-ui][Modal] Apply aria-hidden to the correct elements when Modals are mounted to other places than document.body #43318
base: master
Are you sure you want to change the base?
Conversation
Netlify deploy previewhttps://deploy-preview-43318--material-ui.netlify.app/ @material-ui/core: parsed: +0.06% , gzip: +0.10% Bundle size reportDetails of bundle changes (Toolpad) |
Your argos check seems to be borked especially I made no changed that would affect visuals. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Gr3q, can you point the PR to the master
branch, our current development branch for releases? I'll review it once that's done.
Your argos check seems to be borked especially I made no changed that would affect visuals.
I think its because the target branch is v5
and argos checks against master
.
a7e66a1
to
59f21c9
Compare
Should I not touch the unstable folder in the future? Could you explain why does it exist? |
I reverted the changes in Base UI ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Gr3q Thanks for the pull request.
In addition because we don't differentiate between aria-hidden tags that got added by modals and added by devs, we need to pierce through (remove) every aria-hidden attribute in every ancestor of the last modal container; this is to prevent no accessible elements on a page when multiple modals are present.
I didn't understand this. Can you please explain more clearly with an example?
Previous bug still stands when you mess with aria-hidden states in the tree outside your modal, when the modal gets removed your changes won't be preserved (because the modal will restore the state when it was added)
What bug is this? Can you give a bug reproduction in the form of StackBlitz or CodeSandbox?
Co-authored-by: Zeeshan Tamboli <[email protected]> Signed-off-by: Attila Greguss <[email protected]>
Co-authored-by: Zeeshan Tamboli <[email protected]> Signed-off-by: Attila Greguss <[email protected]>
Co-authored-by: Zeeshan Tamboli <[email protected]> Signed-off-by: Attila Greguss <[email protected]>
If you want to keep the previous behaviour - make only the toplevel modal accessible for screenreaders and to be able to trap focus - then I can't. But I can't say for sure without some real screenreader testing with aria-modals set, like how they handle focus, tabbing, multiple aria-modals, nested aria-modals etc. I could only simplify the code here if they are capable of doing the work for us. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This page is not scrollable: https://deploy-preview-43318--material-ui.netlify.app/material-ui/react-modal/. Maybe some logic is wrong.
I narrowed it down to the server-side modal on the page. I'll check where it's going wrong. Edit: The server-side modal in the docs is always set to open and |
The issue seems to be that the server-side modal has a custom container ( |
@ZeeshanTamboli I'm not sure I have a good answer to that. My assumption is that We made that change because it was not behaving as desired for If they are meant to be different I'm not sure what is the best course of action, In short I can't come up with have any use-cases where the behaviour you are describing is useful by myself. If can provide me one or two I can start implementing something that matches those use cases too |
As per the current production code, the prevention of scrolling is on the You are right that the |
This reverts commit 4b9cf52.
If you want to preserve that behaviour I agree, as long as You did most of the changes there, would you like me to change it now or would you like to do it? |
Please look into it. I don't have the bandwidth for it. |
I'm changing the code, but I want to summarize the bugs this PR had, then what you want. Bugs:
So let me clarify what you want: You want me to change it that scroll lock works peropely when:
and it shouldn't work properly (aka scroll lock applies to the container that effectively does nothing to prevent page scrolling):
I want you to confirm this because this is the only way bugs 1 and 2 can be resolved on the Modal docs page at the same time. (Edit: I'm asking because I will need to implement some workarounds to handle that) |
@Gr3q It's been a while, but from what I remember you're right—that's what's needed. |
@ZeeshanTamboli I fixed the doc page, it does what you want (so no breaking changes). Added a comment that technically the behaviour around the scrolllock+container is still a bug, hopefully someone will remove it when the next major version comes. Fixed the existing tests and added new tests for this too. So now the PR should be ready. 🤞 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Gr3q This looks good to me. I left one comment.
I'm unsure if this will be considered since the focus is shifting to re-implementing Material UI with the new Base UI in the next major release or the one after. I appreciate the time you've invested in this, and I apologize in advance if it doesn’t move forward. However, it might still be possible to release this now or in the next major version. This will definitely need further review. @DiegoAndai, could you take a look?
I think it's still be a while that is released, so it's worth fixing the current version now. |
Hey @Gr3q and @ZeeshanTamboli. First of all, thanks for working on this 🙌🏼
While true, we can still accept and review improvements from the community regarding these topics. So, let's keep working on this. We can land it in v7, which will help many people (given the number of upvotes in the issue). The first thing I would say is that we should change to using It will be a breaking change, but we're already on v7 on the Let me know what you think. |
See conversation from #43318 (review). That wasn't planned back then but maybe we can consider it now for a major release. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I checked the discussion on this PR and also reached out to the Base UI team.
In conclusion, we are not able to stop using aria-hidden
as I suggested. So I would say we should move forward with this PR's intention: fix aria-hidden
handling when disablePortal
is true.
Here's my initial review.
By the way, thanks for working on this @Gr3q
const isPreviousElement = element === previousElement; | ||
|
||
// We came from here | ||
if (isPreviousElement) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If isPreviousElement
is true, it means that we're on the modal or one of its ancestors, right?
// If any ancestor has aria-hidden applied (e.g. by another modal), the current modal could become inaccessible. | ||
// We remove aria-hidden from ancestors to ensure the current modal is accessible, even though this might not be ideal if aria-hidden wasn't added by another modal (For example, if a developer manually applied aria-hidden to hide certain content, removing it could lead to unintended accessibility issues.). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't do this:
If multiple modals are open, or the developer applied aria-hidden
to one of the modal's ancestors, it's the developer responsibility to fix it.
This is not an acceptable side-effect:
[...] if a developer manually applied aria-hidden to hide certain content, removing it could lead to unintended accessibility issues.
// Implement workaround according to | ||
// https://github.com/mui/material-ui/pull/43318#issuecomment-2553509176 | ||
// Technically applying scrollLock to the container does nothing, but | ||
// we preserve the original buggy behavior because fixing it would be | ||
// a breaking change. | ||
// Original behavior: Apply scroll lock to container if it's set, | ||
// otherwise apply to the body element. Because disablePortal | ||
// passes in the correct `containerInfo.container`, the easiest way to | ||
// make it apply to the correct element is to do this. | ||
const container = props.container ? containerInfo.container : document.body; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this related to scroll locking and not aria-hidden? If so, we should move it to a separate PR
const resolvedContainer = disablePortal | ||
? ((mountNodeRef.current ?? modalRef.current)?.parentElement ?? getDoc().body) | ||
: getContainer(container) || getDoc().body; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If providing the container
prop was required when using disablePortal
, this could be simplified to
const resolvedContainer = disablePortal | |
? ((mountNodeRef.current ?? modalRef.current)?.parentElement ?? getDoc().body) | |
: getContainer(container) || getDoc().body; | |
const resolvedContainer = getContainer(container) || getDoc().body; |
Right?
Fixes #19450
Lets do #34165 again. Before if someone used
disablePortal
and opened a modal the whole page became inaccessible to Screen Readers becausearia-hidden
only got applied to siblings of document.body, in this case all of them. This PR fixes that.Changes:
disablePortal
is used.Known problems:
I'll port this to
next
too when I have time.