diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js
index a8218263408936..5592bd52d70b3b 100644
--- a/packages/block-library/src/navigation/edit/index.js
+++ b/packages/block-library/src/navigation/edit/index.js
@@ -7,9 +7,9 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { useState, useEffect, useRef, Platform } from '@wordpress/element';
+import { addQueryArgs } from '@wordpress/url';
import {
InspectorControls,
- BlockControls,
useBlockProps,
__experimentalRecursionProvider as RecursionProvider,
__experimentalUseHasRecursion as useHasRecursion,
@@ -29,7 +29,6 @@ import {
ToggleControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
- ToolbarGroup,
Button,
Spinner,
} from '@wordpress/components';
@@ -136,6 +135,10 @@ function Navigation( {
isError: createNavigationMenuIsError,
} = useCreateNavigationMenu( clientId );
+ const createUntitledEmptyNavigationMenu = () => {
+ createNavigationMenu( '' );
+ };
+
useEffect( () => {
hideNavigationMenuStatusNotice();
@@ -144,8 +147,9 @@ function Navigation( {
}
if ( createNavigationMenuIsSuccess ) {
- setRef( createNavigationMenuPost.id );
- selectBlock( clientId );
+ handleUpdateMenu( createNavigationMenuPost.id, {
+ focusNavigationBlock: true,
+ } );
showNavigationMenuStatusNotice(
__( `Navigation Menu successfully created.` )
@@ -158,7 +162,6 @@ function Navigation( {
);
}
}, [
- createNavigationMenu,
createNavigationMenuStatus,
createNavigationMenuError,
createNavigationMenuPost,
@@ -194,7 +197,6 @@ function Navigation( {
isNavigationMenuResolved,
isNavigationMenuMissing,
navigationMenus,
- navigationMenu,
canUserUpdateNavigationMenu,
hasResolvedCanUserUpdateNavigationMenu,
canUserDeleteNavigationMenu,
@@ -243,8 +245,6 @@ function Navigation( {
const navRef = useRef();
- const isDraftNavigationMenu = navigationMenu?.status === 'draft';
-
const {
convert: convertClassicMenu,
status: classicMenuConversionStatus,
@@ -334,9 +334,15 @@ function Navigation( {
] = useState();
const [ detectedOverlayColor, setDetectedOverlayColor ] = useState();
- const handleUpdateMenu = ( menuId ) => {
+ const handleUpdateMenu = (
+ menuId,
+ options = { focusNavigationBlock: false }
+ ) => {
+ const { focusNavigationBlock } = options;
setRef( menuId );
- selectBlock( clientId );
+ if ( focusNavigationBlock ) {
+ selectBlock( clientId );
+ }
};
useEffect( () => {
@@ -429,27 +435,8 @@ function Navigation( {
ref,
] );
- const navigationSelectorRef = useRef();
- const [ shouldFocusNavigationSelector, setShouldFocusNavigationSelector ] =
- useState( false );
-
- // Focus support after menu selection.
- useEffect( () => {
- if (
- isDraftNavigationMenu ||
- ! isEntityAvailable ||
- ! shouldFocusNavigationSelector
- ) {
- return;
- }
- navigationSelectorRef?.current?.focus();
- setShouldFocusNavigationSelector( false );
- }, [
- isDraftNavigationMenu,
- isEntityAvailable,
- shouldFocusNavigationSelector,
- ] );
-
+ const hasManagePermissions =
+ canUserCreateNavigationMenu || canUserUpdateNavigationMenu;
const isResponsive = 'never' !== overlayMenu;
const overlayMenuPreviewClasses = classnames(
@@ -603,15 +590,13 @@ function Navigation( {
if ( hasUnsavedBlocks ) {
return (
-
-
+
+
{
handleUpdateMenu( menuId );
- setShouldFocusNavigationSelector( true );
} }
onSelectClassicMenu={ async ( classicMenu ) => {
const navMenu = await convertClassicMenu(
@@ -619,17 +604,32 @@ function Navigation( {
classicMenu.name
);
if ( navMenu ) {
- handleUpdateMenu( navMenu.id );
- setShouldFocusNavigationSelector( true );
+ handleUpdateMenu( navMenu.id, {
+ focusNavigationBlock: true,
+ } );
}
} }
- onCreateNew={ () => createNavigationMenu( '', [] ) }
+ onCreateNew={ createUntitledEmptyNavigationMenu }
+ createNavigationMenuIsSuccess={
+ createNavigationMenuIsSuccess
+ }
/* translators: %s: The name of a menu. */
actionLabel={ __( "Switch to '%s'" ) }
- showManageActions
/>
-
-
+
+
+
{ stylingInspectorControls }
-
-
+
+
{
handleUpdateMenu( menuId );
- setShouldFocusNavigationSelector( true );
} }
onSelectClassicMenu={ async ( classicMenu ) => {
const navMenu = await convertClassicMenu(
@@ -687,23 +685,38 @@ function Navigation( {
classicMenu.name
);
if ( navMenu ) {
- handleUpdateMenu( navMenu.id );
- setShouldFocusNavigationSelector( true );
+ handleUpdateMenu( navMenu.id, {
+ focusNavigationBlock: true,
+ } );
}
} }
- onCreateNew={ () => createNavigationMenu( '', [] ) }
+ onCreateNew={ createUntitledEmptyNavigationMenu }
+ createNavigationMenuIsSuccess={
+ createNavigationMenuIsSuccess
+ }
/* translators: %s: The name of a menu. */
actionLabel={ __( "Switch to '%s'" ) }
- showManageActions
/>
-
-
+
+
+
{ __(
'Navigation menu has been deleted or is unavailable. '
) }
);
@@ -771,39 +784,49 @@ function Navigation( {
return (
-
- { ! isDraftNavigationMenu && isEntityAvailable && (
-
- {
- handleUpdateMenu( menuId );
- setShouldFocusNavigationSelector( true );
- } }
- onSelectClassicMenu={ async ( classicMenu ) => {
- const navMenu = await convertClassicMenu(
- classicMenu.id,
- classicMenu.name
- );
- if ( navMenu ) {
- handleUpdateMenu( navMenu.id );
- setShouldFocusNavigationSelector(
- true
- );
- }
- } }
- onCreateNew={ () =>
- createNavigationMenu( '', [] )
+
+
+ {
+ handleUpdateMenu( menuId );
+ } }
+ onSelectClassicMenu={ async ( classicMenu ) => {
+ const navMenu = await convertClassicMenu(
+ classicMenu.id,
+ classicMenu.name
+ );
+ if ( navMenu ) {
+ handleUpdateMenu( navMenu.id, {
+ focusNavigationBlock: true,
+ } );
}
- /* translators: %s: The name of a menu. */
- actionLabel={ __( "Switch to '%s'" ) }
- showManageActions
- />
-
- ) }
-
+ } }
+ onCreateNew={ createUntitledEmptyNavigationMenu }
+ createNavigationMenuIsSuccess={
+ createNavigationMenuIsSuccess
+ }
+ createNavigationMenuIsError={
+ createNavigationMenuIsError
+ }
+ /* translators: %s: The name of a menu. */
+ actionLabel={ __( "Switch to '%s'" ) }
+ />
+
+
+
{ stylingInspectorControls }
{ isEntityAvailable && (
diff --git a/packages/block-library/src/navigation/edit/navigation-menu-selector.js b/packages/block-library/src/navigation/edit/navigation-menu-selector.js
index b83280ec129ec3..04edb53236dae8 100644
--- a/packages/block-library/src/navigation/edit/navigation-menu-selector.js
+++ b/packages/block-library/src/navigation/edit/navigation-menu-selector.js
@@ -5,12 +5,15 @@ import {
MenuGroup,
MenuItem,
MenuItemsChoice,
- ToolbarDropdownMenu,
+ DropdownMenu,
+ Button,
+ VisuallyHidden,
} from '@wordpress/components';
+import { useEntityProp } from '@wordpress/core-data';
+import { Icon, chevronUp, chevronDown } from '@wordpress/icons';
import { __, sprintf } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/html-entities';
-import { addQueryArgs } from '@wordpress/url';
-import { forwardRef, useMemo } from '@wordpress/element';
+import { useEffect, useMemo, useState } from '@wordpress/element';
/**
* Internal dependencies
@@ -18,36 +21,55 @@ import { forwardRef, useMemo } from '@wordpress/element';
import useNavigationMenu from '../use-navigation-menu';
import useNavigationEntities from '../use-navigation-entities';
-function NavigationMenuSelector(
- {
- currentMenuId,
- onSelectNavigationMenu,
- onSelectClassicMenu,
- onCreateNew,
- showManageActions = false,
- actionLabel,
- toggleProps = {},
- },
- forwardedRef
-) {
+function NavigationMenuSelector( {
+ currentMenuId,
+ onSelectNavigationMenu,
+ onSelectClassicMenu,
+ onCreateNew,
+ actionLabel,
+ createNavigationMenuIsSuccess,
+ createNavigationMenuIsError,
+ toggleProps = {},
+} ) {
/* translators: %s: The name of a menu. */
const createActionLabel = __( "Create from '%s'" );
+ const [ selectorLabel, setSelectorLabel ] = useState( '' );
+ const [ isPressed, setIsPressed ] = useState( false );
+ const [ enableOptions, setEnableOptions ] = useState( false );
+ const [ isCreatingMenu, setIsCreatingMenu ] = useState( false );
+
actionLabel = actionLabel || createActionLabel;
const { menus: classicMenus } = useNavigationEntities();
const {
navigationMenus,
+ hasResolvedNavigationMenus,
+ isNavigationMenuResolved,
canUserCreateNavigationMenu,
- canUserUpdateNavigationMenu,
canSwitchNavigationMenu,
} = useNavigationMenu();
+ const [ currentTitle ] = useEntityProp(
+ 'postType',
+ 'wp_navigation',
+ 'title'
+ );
+
+ const shouldEnableMenuSelector =
+ ( canSwitchNavigationMenu || canUserCreateNavigationMenu ) &&
+ hasResolvedNavigationMenus &&
+ ! isCreatingMenu;
+
const menuChoices = useMemo( () => {
return (
navigationMenus?.map( ( { id, title } ) => {
const label = decodeEntities( title.rendered );
+ if ( id === currentMenuId && ! isCreatingMenu ) {
+ setSelectorLabel( currentTitle );
+ setEnableOptions( shouldEnableMenuSelector );
+ }
return {
value: id,
label,
@@ -55,32 +77,90 @@ function NavigationMenuSelector(
};
} ) || []
);
- }, [ navigationMenus ] );
+ }, [
+ currentTitle,
+ currentMenuId,
+ navigationMenus,
+ createNavigationMenuIsSuccess,
+ isNavigationMenuResolved,
+ hasResolvedNavigationMenus,
+ ] );
const hasNavigationMenus = !! navigationMenus?.length;
const hasClassicMenus = !! classicMenus?.length;
const showNavigationMenus = !! canSwitchNavigationMenu;
const showClassicMenus = !! canUserCreateNavigationMenu;
- const hasManagePermissions =
- canUserCreateNavigationMenu || canUserUpdateNavigationMenu;
-
- // Show the selector if:
- // - has switch or create permissions and there are block or classic menus.
- // - user has create or update permissions and component should show the menu actions.
- const showSelectMenus =
- ( ( canSwitchNavigationMenu || canUserCreateNavigationMenu ) &&
- ( hasNavigationMenus || hasClassicMenus ) ) ||
- ( hasManagePermissions && showManageActions );
-
- if ( ! showSelectMenus ) {
- return null;
+
+ const noMenuSelected = hasNavigationMenus && ! currentMenuId;
+ const noBlockMenus = ! hasNavigationMenus && hasResolvedNavigationMenus;
+ const menuUnavailable =
+ hasResolvedNavigationMenus && currentMenuId === null;
+
+ useEffect( () => {
+ if ( ! hasResolvedNavigationMenus ) {
+ setSelectorLabel( __( 'Loading …' ) );
+ } else if ( noMenuSelected || noBlockMenus || menuUnavailable ) {
+ setSelectorLabel( __( 'Select menu' ) );
+ setEnableOptions( shouldEnableMenuSelector );
+ }
+
+ if (
+ isCreatingMenu &&
+ ( createNavigationMenuIsSuccess || createNavigationMenuIsError )
+ ) {
+ setIsCreatingMenu( false );
+ }
+ }, [
+ currentMenuId,
+ hasNavigationMenus,
+ hasResolvedNavigationMenus,
+ createNavigationMenuIsSuccess,
+ isNavigationMenuResolved,
+ ] );
+
+ toggleProps = {
+ ...toggleProps,
+ className: 'wp-block-navigation__navigation-selector-button',
+ children: (
+ <>
+
+ { __( 'Select Menu' ) }
+
+
+ >
+ ),
+ isBusy: ! enableOptions,
+ onClick: () => {
+ setIsPressed( ! isPressed );
+ },
+ };
+
+ if ( ! hasNavigationMenus && ! hasClassicMenus ) {
+ return (
+
+ );
}
return (
-
@@ -91,7 +171,6 @@ function NavigationMenuSelector(
{
- onClose();
onSelectNavigationMenu( menuId );
} }
choices={ menuChoices }
@@ -105,8 +184,12 @@ function NavigationMenuSelector(
return (
+
);
}
-export default forwardRef( NavigationMenuSelector );
+export default NavigationMenuSelector;
diff --git a/packages/block-library/src/navigation/editor.scss b/packages/block-library/src/navigation/editor.scss
index 5e97102c99fd33..b6444c1a331811 100644
--- a/packages/block-library/src/navigation/editor.scss
+++ b/packages/block-library/src/navigation/editor.scss
@@ -615,3 +615,23 @@ body.editor-styles-wrapper
// Override the default padding of ToggleGroupControlOption.
padding: 0 3px;
}
+
+/**
+ * Navigation selector styles
+ */
+.wp-block-navigation__navigation-selector {
+ margin-bottom: $grid-unit-20;
+ width: 100%;
+}
+
+.wp-block-navigation__navigation-selector-button {
+ border: 1px solid;
+ justify-content: space-between;
+ width: 100%;
+}
+
+.wp-block-navigation__navigation-selector-button--createnew {
+ border: 1px solid;
+ margin-bottom: $grid-unit-20;
+ width: 100%;
+}