From 30315599029fff12a6770f0dbe53ea2e6059fb08 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 31 May 2024 04:29:27 -0500 Subject: [PATCH] Don't steal focus when opening browse all blocks from navigation link popover (#61975) When using the browse all blocks button from adding a new navigation link block, the inserter would steal focus from the popover (correctly) and then the popover would close, stealing focus back. To prevent this bug, we check to see if focus is still within the popover at the time of closing. If focus is no longer within it, we don't move focus back to the selected block and instead let whatever stole focus keep the focus. --- .../block-library/src/navigation-link/edit.js | 18 ++++++++++++++++-- .../src/navigation-link/link-ui.js | 6 +++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index 125dd90ee87bec..9e2e171975570f 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -261,6 +261,7 @@ export default function NavigationLinkEdit( { const isDraggingWithin = useIsDraggingWithin( listItemRef ); const itemLabelPlaceholder = __( 'Add label…' ); const ref = useRef(); + const linkUIref = useRef(); const prevUrl = usePrevious( url ); // Change the label using inspector causes rich text to change focus on firefox. @@ -570,14 +571,27 @@ export default function NavigationLinkEdit( { ) } { isLinkOpen && ( { // If there is no link then remove the auto-inserted block. // This avoids empty blocks which can provided a poor UX. if ( ! url ) { - // Select the previous block to keep focus nearby - selectPreviousBlock( clientId, true ); + // Fixes https://github.com/WordPress/gutenberg/issues/61361 + // There's a chance we're closing due to the user selecting the browse all button. + // Only move focus if the focus is still within the popover ui. If it's not within + // the popover, it's because something has taken the focus from the popover, and + // we don't want to steal it back. + if ( + linkUIref.current.contains( + window.document.activeElement + ) + ) { + // Select the previous block to keep focus nearby + selectPreviousBlock( clientId, true ); + } + // Remove the link. onReplace( [] ); return; diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index ce79af40e4708c..6619c46253546e 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -20,6 +20,7 @@ import { useState, useRef, useEffect, + forwardRef, } from '@wordpress/element'; import { store as coreStore, @@ -145,7 +146,7 @@ function LinkUIBlockInserter( { clientId, onBack, onSelectBlock } ) { ); } -export function LinkUI( props ) { +function UnforwardedLinkUI( props, ref ) { const [ addingBlock, setAddingBlock ] = useState( false ); const [ focusAddBlockButton, setFocusAddBlockButton ] = useState( false ); const { saveEntityRecord } = useDispatch( coreStore ); @@ -214,6 +215,7 @@ export function LinkUI( props ) { return ( { const blockInserterAriaRole = 'listbox'; const addBlockButtonRef = useRef();