Skip to content
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

Merged
merged 13 commits into from
Oct 17, 2023
Merged

Conversation

jadutter
Copy link
Contributor

@jadutter jadutter commented Oct 9, 2023

Description

  • Improve accessibility
    • adjusted how focus is handled when the modal opens and closes
    • added some aria attributes to increase accessibility
    • Updated the prerender modal close button to receive focus when opened
  • Updated the prerender modal
    • close button to look identical to the modal close button
    • cleaned up some lint issues
  • Removed unused code useAutoFocus
  • Improve debugging
    • added debug levels to control logging verbosity
    • added debug messages and listeners to view events and their order
    • split into a separate PR

Screenshots

Testing instructions

- 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
@jadutter jadutter changed the title fix: safari focus fix: safari focus (DTCRCGEMI-1356) Oct 9, 2023
const btn = document.querySelector('.close');
btn?.focus();
// give the document time to update before trying to focus the close button
setTimeout(() => {
Copy link
Collaborator

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.

Copy link
Contributor Author

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

  1. The the close button for the modal needed the autofocus attribute
  2. The iframe for the modal in the parent page needed to receive focus
  3. 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

  1. on the parent page, I would need to listen for when the iframe received focus, then pass the info onto
  2. the zoid event emitter in the parent page, the pass the info onto
  3. 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.

Copy link
Contributor Author

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

Copy link
Contributor Author

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:

  1. We'll need to revisit making sure the prerender modal is accessible. I tried to clean it up a bit, but
    1. I couldn't get its close button to receive focus after opening, closing, and opening again.
    2. 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"
  2. 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

src/components/modal/v2/parts/BodyContent.jsx Show resolved Hide resolved
src/components/modal/v2/parts/BodyContent.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/components/modal/v2/lib/providers/transition.js Outdated Show resolved Hide resolved
src/library/zoid/message/component.js Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Show resolved Hide resolved
src/library/zoid/modal/prerenderTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/prerenderTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/prerenderTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/containerTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/prerenderTemplate.jsx Outdated Show resolved Hide resolved
src/library/zoid/modal/prerenderTemplate.jsx Outdated Show resolved Hide resolved
@merlinpaypal merlinpaypal merged commit 5b4a823 into paypal:develop Oct 17, 2023
41 checks passed
@merlinpaypal merlinpaypal changed the title fix: safari focus (DTCRCGEMI-1356) fix: safari focus Oct 17, 2023
@jadutter jadutter mentioned this pull request Oct 17, 2023
github-actions bot pushed a commit that referenced this pull request Oct 18, 2023
### [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))
@github-actions
Copy link

🎉 This PR is included in version 1.49.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Successfully merging this pull request may close these issues.

4 participants