diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js index fb3e1abb4d5..f914752df06 100644 --- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js +++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js @@ -3262,9 +3262,9 @@ function blurActiveElementWithinFragment( return false; } const instance = getInstanceFromHostFiber(child); - if (instance === activeElement) { + if (instance === activeElement || instance.contains(activeElement)) { // $FlowFixMe[prop-missing] - instance.blur(); + activeElement.blur(); return true; } return false; diff --git a/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js b/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js index 628ebc85bf7..5c55ceffafe 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js @@ -454,6 +454,36 @@ describe('FragmentRefs', () => { expect(document.activeElement).toEqual(document.body); }); + // @gate enableFragmentRefs + it('removes focus from a nested element inside of the Fragment', async () => { + const fragmentRef = React.createRef(); + const root = ReactDOMClient.createRoot(container); + + function Test() { + return ( + +
+ +
+
+ ); + } + + await act(() => { + root.render(); + }); + + await act(() => { + fragmentRef.current.focus(); + }); + expect(document.activeElement.id).toEqual('nested-input'); + + await act(() => { + fragmentRef.current.blur(); + }); + expect(document.activeElement).toEqual(document.body); + }); + // @gate enableFragmentRefs it('does not remove focus from elements outside of the Fragment', async () => { const fragmentRefA = React.createRef();