-
Notifications
You must be signed in to change notification settings - Fork 13.4k
fix(overlays): do not return focus if application has already moved focus manually #28850
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -496,7 +496,7 @@ export const present = async <OverlayPresentOptions>( | |
* from returning focus as a result. | ||
*/ | ||
if (overlay.el.tagName !== 'ION-TOAST') { | ||
focusPreviousElementOnDismiss(overlay.el); | ||
restoreElementFocus(overlay.el); | ||
} | ||
|
||
/** | ||
|
@@ -520,7 +520,7 @@ export const present = async <OverlayPresentOptions>( | |
* to where they were before they | ||
* opened the overlay. | ||
*/ | ||
const focusPreviousElementOnDismiss = async (overlayEl: any) => { | ||
const restoreElementFocus = async (overlayEl: any) => { | ||
let previousElement = document.activeElement as HTMLElement | null; | ||
if (!previousElement) { | ||
return; | ||
|
@@ -533,7 +533,34 @@ const focusPreviousElementOnDismiss = async (overlayEl: any) => { | |
} | ||
|
||
await overlayEl.onDidDismiss(); | ||
previousElement.focus(); | ||
|
||
/** | ||
* After onDidDismiss, the overlay loses focus | ||
* because it is removed from the document | ||
* | ||
* > An element will also lose focus [...] | ||
* > if the element is removed from the document) | ||
* | ||
* https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event | ||
* | ||
* Additionally, `document.activeElement` returns: | ||
* | ||
* > The Element which currently has focus, | ||
* > `<body>` or null if there is | ||
* > no focused element. | ||
* | ||
* https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement#value | ||
* | ||
* However, if the user has already focused | ||
* an element sometime between onWillDismiss | ||
* and onDidDismiss (for example, focusing a | ||
* text box after tapping a button in an | ||
* action sheet) then don't restore focus to | ||
* previous element | ||
*/ | ||
if (document.activeElement === null || document.activeElement === document.body) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we also add a comment that explains focus is always moved to the body when the overlay is dismissed? Maintainers may not know why we specifically check the body here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added some MDN references. Apologies if its now a bit too wordy, feel free to make further suggestions! |
||
previousElement.focus(); | ||
} | ||
}; | ||
|
||
export const dismiss = async <OverlayDismissOptions>( | ||
|
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'll need a test for this. Something like the following should suffice:
You can put this in
src/utils/test/overlays/overlays.e2e.ts
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.
Done thanks!