From a3c1e51aa9d5d6552e13f2aa5fdf79a78bebbcad Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 10 Sep 2024 21:08:08 -0400 Subject: [PATCH] Add back previous checks --- packages/react/focus-scope/src/FocusScope.tsx | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/react/focus-scope/src/FocusScope.tsx b/packages/react/focus-scope/src/FocusScope.tsx index 654f4e763..585810e6d 100644 --- a/packages/react/focus-scope/src/FocusScope.tsx +++ b/packages/react/focus-scope/src/FocusScope.tsx @@ -108,13 +108,27 @@ const FocusScope = React.forwardRef((props, // When the focused element gets removed from the DOM, browsers move focus // back to the document.body. In this case, we move focus to the container // to keep focus trapped correctly. - function handleMutations() { + function handleMutations(mutations: MutationRecord[]) { + // If the activeElement is not the document body, then the focus was not + // lost, so we don't need to rescue the focus. Please note that this is + // not perfectly robust, because the active element can still be + // document.body even in some cases where the focus was not lost. For + // example, during a blur event, browsers set the activeElement to + // document.body just before activeElement may be set to the next + // element + if (document.activeElement !== document.body) return; + + // If no elements were removed, then we don't need to rescue focus + if (noElementsRemoved(mutations)) return; + + // If the last focused element is still in the container, then it wasn't + // removed and we don't need to rescue focus const lastFocusedElementStillInContainer = container?.contains( lastFocusedElementRef.current ); - if (!lastFocusedElementStillInContainer) { - focus(container); - } + if (lastFocusedElementStillInContainer) return; + + focus(container); } document.addEventListener('focusin', handleFocusIn); @@ -343,6 +357,15 @@ function removeLinks(items: HTMLElement[]) { return items.filter((item) => item.tagName !== 'A'); } +function noElementsRemoved(mutations: MutationRecord[]) { + for (const mutation of mutations) { + if (mutation.removedNodes.length > 0) { + return false; + } + } + return true; +} + const Root = FocusScope; export {