-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Modal
: Fix loss of focus when clicking outside
#52653
Conversation
b9c7705
to
91822b7
Compare
Flaky tests detected in 2750830. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5660909745
|
91822b7
to
4a3099d
Compare
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 works as described, but it leaves me wondering why useFocusOutside()
was necessary in the first place. Do you know? Since tabbing is constrained to the modal, wouldn't a click on the overlay be the only way that focus would move outside the modal?
I've even noticed that only relying on useFocusOutside
to detect clicks on the overlay doesn't even work reliably when iframes are involved. For example in the Storybook in Canvas mode, if you open the modal, click outside the story iframe, then click on the overlay, it doesn't close.
It seems like a click handler on the overlay like in this PR is better and sufficient.
Thanks for having a look Lena 🙇
🤓 As best I can tell it never was technically necessary. The component had an overlay element and constrained tabbing from the start #6261 so you'd think it might have used a simple click handler on the overlay. Instead it used a more generalized approach provided by an HOC of an external library. Later that was replaced by the
Practically speaking yes. Focus can be moved programmatically but I don't think that was intentionally supported or relied upon.
Well, yeah that’s #51602 which removes the hook from the Modal. That stalled mostly because there’s one case of unintentional reliance on closing the modal when focus moves outside programmatically. Also, there is some desire to update |
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.
Thanks for explaining how this relates to the other PRs 🙏 I think it makes sense to merge this to fix the immediate problem with the focus returning then!
@@ -179,6 +188,9 @@ function UnforwardedModal( | |||
overlayClassName | |||
) } | |||
onKeyDown={ handleEscapeKeyDown } | |||
onPointerDown={ |
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.
Can we add a TODO comment here? Something to the effect of "Reconcile with useFocusOutside
" and "Ideally this should be an onClick".
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.
I gave it my best and hopefully it captures what you had in mind. At least regarding the first part. I left out the bit about preferring onClick
. That could provide some nuance to the interaction but I think handling pointerdown
will still be necessary. That’s because if the default isn't prevented from pointerdown
focus will move and be left unreturned by useFocusReturn
.
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.
It does 👍 I'm mostly concerned that we're treating a mere pointerdown
as a click
intent, which isn't technically true. For example I sometimes mousedown
on a button but change my mind and drag away so it doesn't go through as a click
.
But I guess we could even resolve that right now, if we just event.preventDefault()
on the pointerdown
, and wait until the click
event to actually call onRequestClose()
.
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.
Yep, that's just what I meant about nuance in the interaction. I do the same sometimes. To keep current behavior and this PR focused, I'd left it as is.
Since you agree it should be resolved I went ahead and tried it. It's not quite as simple as we likely both thought. It's also an opportunity to try a bit of further nuance as suggested by Aki #51602 (comment). So I've got a branch for it and will make it a separate PR.
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.
…and that PR #52994
4a3099d
to
d1f8cb2
Compare
d1f8cb2
to
2750830
Compare
What?
Modal
component works when it’s dismissed by clicking outside.Why?
Focus loss is troublesome in various ways. This fixes #51722.
How?
Uses a pointer event handler to preempt the
onFocusOutside
handling for dismissing the modal when clicking outside.Testing Instructions
This can be generalized to any modal/confirmation dialog in any of the block editors.
Testing Instructions for Keyboard
After step 4 of the above testing instructions you can try using editor keyboard shortcuts and observe they do work.
Unit Test Testing Instructions
git checkout 1aaa194
npm run test:unit -- modal/test/index.tsx
git switch -