-
Notifications
You must be signed in to change notification settings - Fork 57
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
fix: safari focus #997
fix: safari focus #997
Conversation
- added debug messages and listeners to view events and their order - adjusted how focus is handled when the modal opens and closes - added some aria attributes to increase accessibility
const btn = document.querySelector('.close'); | ||
btn?.focus(); | ||
// give the document time to update before trying to focus the close button | ||
setTimeout(() => { |
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 there an event we should be looking for like the document DOMContentLoaded
or window load
event? If so would we be able to leverage these either of these helpers? https://github.com/paypal/paypal-messaging-components/blob/develop/src/utils/events.js#L11-L21. If we aren't waiting for a specific DOM event and just need to ensure the browser has had a render cycle, could we use requestAnimationFrame
instead? The primary concern with setTimeout
is it is an arbitrary time that may or may not fire the same based on device performance.
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.
While manually testing in Safari, I found that
- The the close button for the modal needed the
autofocus
attribute - The
iframe
for the modal in the parent page needed to receive focus - The close button for the modal needed to receive focus
The events appeared to be happening in the correct order, but from what I could tell, the iframe was going to be given focus, but had not yet received focus (I found something similar happening with the tabTrap).
I thought about setting up listeners to ensure the button focused happened after the iframe
, but I realized I would need
- on the parent page, I would need to listen for when the iframe received focus, then pass the info onto
- the zoid event emitter in the parent page, the pass the info onto
- a listener in the child iframe, that would finally add focus to the button
I thought about it some more, and I figured the direct pipeline I would setup would be unideal. We are already using MODAL_EVENT.MODAL_SHOW
to communicate almost the same thing. Creating a pipelline for MODAL_EVENT.FOCUS
seemed like a lot of extra code to add onto messaging just to focus the close button.
I found that bumping it to a different place in the event cycle was enough for it to behave correctly though, not necessarily needing to wait literally 10ms.
I'll change it to requestAnimationFrame
since it appears to work too.
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.
After further testing, I've realized my PR only partially fixed the issue:
- modal open
- modal close
- message has focus
- modal open
- modal close
- modal still has focus
Going to keep working on it
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've gotten it to a decent state, I think. The two caveats I'm thinking of are:
- We'll need to revisit making sure the prerender modal is accessible. I tried to clean it up a bit, but
- I couldn't get its close button to receive focus after opening, closing, and opening again.
- I wasn't at all certain how to effectively communicate via accessibility tags to a non-visual user "you are on a modal that is currently loading content" or announce "the modal has failed to load"
- The modal button receives focus in Chrome, but only the modal receives focus in Safari. Apparently, Apple intends this as a "feature"; the user must directly interact with the iframe before any elements in the iframe can be given focus. After the user interacts with the elements within the iframe for the modal, then we can call
focus()
on the close button. Since the modal can still be navigated after the iframe for the modal receives focus, I was going to let this one go
### [1.49.2](v1.49.1...v1.49.2) (2023-10-18) ### Bug Fixes * prevent undefined device ID when namespace ([#994](#994)) ([fe91522](fe91522)) * safari focus ([#1005](#1005)) ([827a56d](827a56d)) * safari focus ([#997](#997)) ([5b4a823](5b4a823)) ### Code Refactoring * disable tab trap on api or lander ([#999](#999)) ([ab92760](ab92760))
🎉 This PR is included in version 1.49.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Description
useAutoFocus
Improve debuggingadded debug levels to control logging verbosityadded debug messages and listeners to view events and their orderScreenshots
Testing instructions