Skip to content

Commit 4d503c4

Browse files
authored
Navigation block: After choosing an option from Select Menu, focus after block rerender (#40390)
* Focus the select menu button after selection is made. * Add E2E test. * Add code comments to E2E test.
1 parent 1e06cba commit 4d503c4

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

packages/block-library/src/navigation/edit/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ function Navigation( {
523523
ref,
524524
] );
525525

526+
const navigationSelectorRef = useRef();
527+
const [
528+
shouldFocusNavigationSelector,
529+
setShouldFocusNavigationSelector,
530+
] = useState( false );
526531
const handleSelectNavigation = useCallback(
527532
( navPostOrClassicMenu ) => {
528533
if ( ! navPostOrClassicMenu ) {
@@ -538,10 +543,28 @@ function Navigation( {
538543
} else {
539544
handleUpdateMenu( navPostOrClassicMenu.id );
540545
}
546+
setShouldFocusNavigationSelector( true );
541547
},
542548
[ convert, handleUpdateMenu ]
543549
);
544550

551+
// Focus support after menu selection.
552+
useEffect( () => {
553+
if (
554+
isDraftNavigationMenu ||
555+
! isEntityAvailable ||
556+
! shouldFocusNavigationSelector
557+
) {
558+
return;
559+
}
560+
navigationSelectorRef?.current?.focus();
561+
setShouldFocusNavigationSelector( false );
562+
}, [
563+
isDraftNavigationMenu,
564+
isEntityAvailable,
565+
shouldFocusNavigationSelector,
566+
] );
567+
545568
const resetToEmptyBlock = useCallback( () => {
546569
registry.batch( () => {
547570
if ( navigationArea ) {
@@ -663,6 +686,7 @@ function Navigation( {
663686
{ ! isDraftNavigationMenu && isEntityAvailable && (
664687
<ToolbarGroup className="wp-block-navigation__toolbar-menu-selector">
665688
<NavigationMenuSelector
689+
ref={ navigationSelectorRef }
666690
currentMenuId={ ref }
667691
clientId={ clientId }
668692
onSelect={ handleSelectNavigation }

packages/block-library/src/navigation/edit/navigation-menu-selector.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,25 @@ import {
1010
import { __, sprintf } from '@wordpress/i18n';
1111
import { decodeEntities } from '@wordpress/html-entities';
1212
import { addQueryArgs } from '@wordpress/url';
13-
import { useCallback, useMemo } from '@wordpress/element';
13+
import { forwardRef, useCallback, useMemo } from '@wordpress/element';
1414

1515
/**
1616
* Internal dependencies
1717
*/
1818
import useNavigationMenu from '../use-navigation-menu';
1919
import useNavigationEntities from '../use-navigation-entities';
2020

21-
export default function NavigationMenuSelector( {
22-
currentMenuId,
23-
onSelect,
24-
onCreateNew,
25-
showManageActions = false,
26-
actionLabel,
27-
toggleProps = {},
28-
} ) {
21+
function NavigationMenuSelector(
22+
{
23+
currentMenuId,
24+
onSelect,
25+
onCreateNew,
26+
showManageActions = false,
27+
actionLabel,
28+
toggleProps = {},
29+
},
30+
forwardedRef
31+
) {
2932
/* translators: %s: The name of a menu. */
3033
const createActionLabel = __( "Create from '%s'" );
3134

@@ -92,6 +95,7 @@ export default function NavigationMenuSelector( {
9295

9396
return (
9497
<ToolbarDropdownMenu
98+
ref={ forwardedRef }
9599
label={ __( 'Select Menu' ) }
96100
text={ __( 'Select Menu' ) }
97101
icon={ null }
@@ -152,3 +156,5 @@ export default function NavigationMenuSelector( {
152156
</ToolbarDropdownMenu>
153157
);
154158
}
159+
160+
export default forwardRef( NavigationMenuSelector );

packages/e2e-tests/specs/editor/blocks/navigation.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,5 +1429,43 @@ describe( 'Navigation', () => {
14291429
'//*[contains(@class, "components-snackbar")]/*[text()="Navigation Menu successfully created."]'
14301430
);
14311431
} );
1432+
1433+
it( 'should always focus select menu button after item selection', async () => {
1434+
// Create some navigation menus to work with.
1435+
await createNavigationMenu( {
1436+
title: 'Example Navigation',
1437+
content:
1438+
'<!-- wp:navigation-link {"label":"WordPress","type":"custom","url":"http://www.wordpress.org/","kind":"custom","isTopLevelLink":true} /-->',
1439+
} );
1440+
await createNavigationMenu( {
1441+
title: 'Second Example Navigation',
1442+
content:
1443+
'<!-- wp:navigation-link {"label":"WordPress","type":"custom","url":"http://www.wordpress.org/","kind":"custom","isTopLevelLink":true} /-->',
1444+
} );
1445+
1446+
// Create new post.
1447+
await createNewPost();
1448+
1449+
// Insert new block and wait for the insert to complete.
1450+
await insertBlock( 'Navigation' );
1451+
await waitForBlock( 'Navigation' );
1452+
await page.waitForXPath( START_EMPTY_XPATH );
1453+
1454+
// Change menus via the select menu toolbar button.
1455+
const selectMenuDropdown = await page.waitForSelector(
1456+
'[aria-label="Select Menu"]'
1457+
);
1458+
await selectMenuDropdown.click();
1459+
const exampleNavigationOption = await page.waitForXPath(
1460+
'//span[contains(text(), "Second Example Navigation")]'
1461+
);
1462+
await exampleNavigationOption.click();
1463+
1464+
// Once the options are closed, does select menu button receive focus?
1465+
const selectMenuDropdown2 = await page.waitForSelector(
1466+
'[aria-label="Select Menu"]'
1467+
);
1468+
await expect( selectMenuDropdown2 ).toHaveFocus();
1469+
} );
14321470
} );
14331471
} );

0 commit comments

Comments
 (0)