diff --git a/lib/navigation.php b/lib/navigation.php
index b1e7d21b031589..7bfe3416647c6e 100644
--- a/lib/navigation.php
+++ b/lib/navigation.php
@@ -299,9 +299,14 @@ function gutenberg_output_block_nav_menu( $output, $args ) {
$menu_items_by_parent_id[ $menu_item->menu_item_parent ][] = $menu_item;
}
+ $block_attributes = array();
+ if ( isset( $args->block_attributes ) ) {
+ $block_attributes = $args->block_attributes;
+ }
+
$navigation_block = array(
'blockName' => 'core/navigation',
- 'attrs' => array(),
+ 'attrs' => $block_attributes,
'innerBlocks' => gutenberg_convert_menu_items_to_blocks(
isset( $menu_items_by_parent_id[0] )
? $menu_items_by_parent_id[0]
diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json
index 28c7d25a89ea68..a354926b635b5f 100644
--- a/packages/block-library/src/navigation/block.json
+++ b/packages/block-library/src/navigation/block.json
@@ -3,6 +3,9 @@
"name": "core/navigation",
"category": "design",
"attributes": {
+ "location": {
+ "type": "string"
+ },
"orientation": {
"type": "string"
},
diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js
index 18d9da732015c9..961cde395d570e 100644
--- a/packages/block-library/src/navigation/edit.js
+++ b/packages/block-library/src/navigation/edit.js
@@ -100,6 +100,8 @@ function Navigation( {
return (
{
setIsPlaceholderShown( false );
updateInnerBlocks( blocks );
diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php
index b1fe553df3b3fb..be166b3894a4be 100644
--- a/packages/block-library/src/navigation/index.php
+++ b/packages/block-library/src/navigation/index.php
@@ -85,6 +85,41 @@ function block_core_navigation_build_css_font_sizes( $attributes ) {
return $font_sizes;
}
+/**
+ * Renders a Navigation Block derived from data from the theme_location assigned
+ * via the block attribute 'location'.
+ *
+ * If the theme doesn't explicity support 'block-nav-menus' or no location was provided
+ * as a block attribute then an empty string is returned.
+ *
+ * @param array $attributes Navigation block attributes.
+ * @return string HTML markup of a generated Navigation Block.
+ */
+function get_classic_navigation_elements( $attributes ) {
+
+ if ( ! current_theme_supports( 'block-nav-menus' ) ) {
+ return '';
+ }
+
+ if ( ! array_key_exists( 'location', $attributes ) ) {
+ return '';
+ }
+
+ $block_attributes = $attributes;
+ unset( $block_attributes['location'] );
+
+ return wp_nav_menu(
+ array(
+ 'theme_location' => $attributes['location'],
+ 'block_attributes' => $block_attributes,
+ 'container' => '',
+ 'items_wrap' => '%3$s',
+ 'fallback_cb' => false,
+ 'echo' => false,
+ )
+ );
+}
+
/**
* Returns the top-level submenu SVG chevron icon.
*
@@ -122,7 +157,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {
unset( $attributes['rgbTextColor'], $attributes['rgbBackgroundColor'] );
if ( empty( $block->inner_blocks ) ) {
- return '';
+ return get_classic_navigation_elements( $attributes );
}
$colors = block_core_navigation_build_css_colors( $attributes );
diff --git a/packages/block-library/src/navigation/placeholder.js b/packages/block-library/src/navigation/placeholder.js
index c0ac1b6ff4c301..eb6a853ad0ae4b 100644
--- a/packages/block-library/src/navigation/placeholder.js
+++ b/packages/block-library/src/navigation/placeholder.js
@@ -98,7 +98,7 @@ function convertMenuItemsToBlocks( menuItems ) {
return mapMenuItemsToBlocks( menuTree );
}
-function NavigationPlaceholder( { onCreate }, ref ) {
+function NavigationPlaceholder( { location, onCreate, setAttributes }, ref ) {
const [ selectedMenu, setSelectedMenu ] = useState();
const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false );
@@ -108,6 +108,7 @@ function NavigationPlaceholder( { onCreate }, ref ) {
isResolvingPages,
hasResolvedPages,
menus,
+ menuLocations,
isResolvingMenus,
hasResolvedMenus,
menuItems,
@@ -118,6 +119,7 @@ function NavigationPlaceholder( { onCreate }, ref ) {
getEntityRecords,
getMenus,
getMenuItems,
+ getMenuLocations,
isResolving,
hasFinishedResolution,
} = select( coreStore );
@@ -167,6 +169,7 @@ function NavigationPlaceholder( { onCreate }, ref ) {
menuItemsParameters
)
: false,
+ menuLocations: getMenuLocations(),
};
},
[ selectedMenu ]
@@ -216,6 +219,131 @@ function NavigationPlaceholder( { onCreate }, ref ) {
isPrimary: true,
className: 'wp-block-navigation-placeholder__actions__dropdown',
};
+
+ const locationPlaceholder = () => {
+ if ( ! location || ! menuLocations ) {
+ return;
+ }
+
+ const selectedMenuLocation = menuLocations.find(
+ ( menuLocation ) => menuLocation.name === location
+ );
+
+ if ( ! selectedMenuLocation ) {
+ return;
+ }
+
+ return (
+ <>
+ { ' ' }
+
+ { ( { onClose } ) => (
+
+ { menuLocations.map( ( { name, description } ) => {
+ return (
+
+ );
+ } ) }
+
+ ) }
+
+
+
+ >
+ );
+ };
+
+ const convertToBlocks = () => {
+ setAttributes( { location: null } );
+ };
+
+ const convertToClassic = ( newLocation ) => {
+ setAttributes( { location: newLocation.name } );
+ };
+
+ const defaultPlaceholder = () => {
+ if ( location ) {
+ return;
+ }
+
+ const defaultClassicMenuLocation = menuLocations?.[ 0 ];
+
+ return (
+ <>
+ { hasMenus ? (
+
+ { ( { onClose } ) => (
+
+ { menus.map( ( menu ) => {
+ return (
+
+ );
+ } ) }
+
+ ) }
+
+ ) : undefined }
+
+ { hasPages ? (
+
+ ) : undefined }
+
+ { !! defaultClassicMenuLocation ? (
+
+ ) : null }
+ >
+ );
+ };
+
return (
@@ -234,46 +362,9 @@ function NavigationPlaceholder( { onCreate }, ref ) {
{ __( 'Navigation' ) }
- { hasMenus ? (
-
- { ( { onClose } ) => (
-
- { menus.map( ( menu ) => {
- return (
-
- );
- } ) }
-
- ) }
-
- ) : undefined }
- { hasPages ? (
-
- ) : undefined }
-
+
+ { locationPlaceholder() }
+ { defaultPlaceholder() }
) }