+
%2$s
@@ -633,13 +689,18 @@ function render_block_core_navigation( $attributes, $content, $block ) {
esc_attr( safecss_filter_attr( $colors['overlay_inline_styles'] ) ),
__( 'Menu' ),
$toggle_button_content,
- $toggle_close_button_content
+ $toggle_close_button_content,
+ $open_button_directives,
+ $responsive_container_directives,
+ $responsive_dialog_directives,
+ $close_button_directives
);
return sprintf(
- '
',
+ '
',
$wrapper_attributes,
- $responsive_container_markup
+ $responsive_container_markup,
+ $nav_element_directives
);
}
@@ -902,3 +963,66 @@ function block_core_navigation_get_most_recently_published_navigation() {
return null;
}
+
+/**
+ * Add Interactivity API directives to the navigation-submenu and page-list blocks markup using the Tag Processor
+ * The final HTML of the navigation-submenu and the page-list blocks will look similar to this:
+ *
+ *
+ *
+ * Title
+ *
+ *
+ *
+ * @param string $w Markup of the navigation block.
+ * @param array $block_attributes Block attributes.
+ *
+ * @return string Submenu markup with the directives injected.
+ */
+function gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes ) {
+ while ( $w->next_tag(
+ array(
+ 'tag_name' => 'LI',
+ 'class_name' => 'has-child',
+ )
+ ) ) {
+ // Add directives to the parent `
`.
+ $w->set_attribute( 'data-wp-interactive', true );
+ $w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": false } } }' );
+ $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
+ $w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
+ $w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
+ if ( ! isset( $block_attributes['openSubmenusOnClick'] ) || false === $block_attributes['openSubmenusOnClick'] ) {
+ $w->set_attribute( 'data-wp-on--mouseenter', 'actions.core.navigation.openMenuOnHover' );
+ $w->set_attribute( 'data-wp-on--mouseleave', 'actions.core.navigation.closeMenuOnHover' );
+ }
+
+ // Add directives to the toggle submenu button.
+ if ( $w->next_tag(
+ array(
+ 'tag_name' => 'BUTTON',
+ 'class_name' => 'wp-block-navigation-submenu__toggle',
+ )
+ ) ) {
+ $w->set_attribute( 'data-wp-on--click', 'actions.core.navigation.toggleMenuOnClick' );
+ $w->set_attribute( 'data-wp-bind--aria-expanded', 'selectors.core.navigation.isMenuOpen' );
+ };
+
+ // Iterate through subitems if exist.
+ gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes );
+ }
+ return $w->get_updated_html();
+};
diff --git a/packages/block-library/src/navigation/interactivity.js b/packages/block-library/src/navigation/interactivity.js
index dfc9cb0f9c4a5..210e82a378667 100644
--- a/packages/block-library/src/navigation/interactivity.js
+++ b/packages/block-library/src/navigation/interactivity.js
@@ -111,7 +111,7 @@ store( {
},
handleMenuKeydown: ( args ) => {
const { context, event } = args;
- if ( context.core.navigation.isMenuOpen ) {
+ if ( context.core.navigation.isMenuOpen.click ) {
// If Escape close the menu
if (
event?.key === 'Escape' ||
diff --git a/packages/block-library/src/navigation/view-modal.js b/packages/block-library/src/navigation/view-modal.js
deleted file mode 100644
index 9477d262816d9..0000000000000
--- a/packages/block-library/src/navigation/view-modal.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * External dependencies
- */
-import MicroModal from 'micromodal';
-
-// Responsive navigation toggle.
-function navigationToggleModal( modal ) {
- const dialogContainer = modal.querySelector(
- `.wp-block-navigation__responsive-dialog`
- );
-
- const isHidden = 'true' === modal.getAttribute( 'aria-hidden' );
-
- modal.classList.toggle( 'has-modal-open', ! isHidden );
- dialogContainer.toggleAttribute( 'aria-modal', ! isHidden );
-
- if ( isHidden ) {
- dialogContainer.removeAttribute( 'role' );
- dialogContainer.removeAttribute( 'aria-modal' );
- } else {
- dialogContainer.setAttribute( 'role', 'dialog' );
- dialogContainer.setAttribute( 'aria-modal', 'true' );
- }
-
- // Add a class to indicate the modal is open.
- const htmlElement = document.documentElement;
- htmlElement.classList.toggle( 'has-modal-open' );
-}
-
-function isLinkToAnchorOnCurrentPage( node ) {
- return (
- node.hash &&
- node.protocol === window.location.protocol &&
- node.host === window.location.host &&
- node.pathname === window.location.pathname &&
- node.search === window.location.search
- );
-}
-
-window.addEventListener( 'load', () => {
- MicroModal.init( {
- onShow: navigationToggleModal,
- onClose: navigationToggleModal,
- openClass: 'is-menu-open',
- } );
-
- // Close modal automatically on clicking anchor links inside modal.
- const navigationLinks = document.querySelectorAll(
- '.wp-block-navigation-item__content'
- );
-
- navigationLinks.forEach( function ( link ) {
- // Ignore non-anchor links and anchor links which open on a new tab.
- if (
- ! isLinkToAnchorOnCurrentPage( link ) ||
- link.attributes?.target === '_blank'
- ) {
- return;
- }
-
- // Find the specific parent modal for this link
- // since .close() won't work without an ID if there are
- // multiple navigation menus in a post/page.
- const modal = link.closest(
- '.wp-block-navigation__responsive-container'
- );
- const modalId = modal?.getAttribute( 'id' );
-
- link.addEventListener( 'click', () => {
- // check if modal exists and is open before trying to close it
- // otherwise Micromodal will toggle the `has-modal-open` class
- // on the html tag which prevents scrolling
- if ( modalId && modal.classList.contains( 'has-modal-open' ) ) {
- MicroModal.close( modalId );
- }
- } );
- } );
-} );
diff --git a/packages/block-library/src/navigation/view.js b/packages/block-library/src/navigation/view.js
deleted file mode 100644
index 19805a44ae4ae..0000000000000
--- a/packages/block-library/src/navigation/view.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// Open on click functionality.
-function closeSubmenus( element ) {
- element
- .querySelectorAll( '[aria-expanded="true"]' )
- .forEach( function ( toggle ) {
- toggle.setAttribute( 'aria-expanded', 'false' );
- } );
-}
-
-function toggleSubmenuOnClick( event ) {
- const buttonToggle = event.target.closest( '[aria-expanded]' );
- const isSubmenuOpen = buttonToggle.getAttribute( 'aria-expanded' );
-
- if ( isSubmenuOpen === 'true' ) {
- closeSubmenus( buttonToggle.closest( '.wp-block-navigation-item' ) );
- } else {
- // Close all sibling submenus.
- const parentElement = buttonToggle.closest(
- '.wp-block-navigation-item'
- );
- const navigationParent = buttonToggle.closest(
- '.wp-block-navigation__submenu-container, .wp-block-navigation__container, .wp-block-page-list'
- );
- navigationParent
- .querySelectorAll( '.wp-block-navigation-item' )
- .forEach( function ( child ) {
- if ( child !== parentElement ) {
- closeSubmenus( child );
- }
- } );
- // Open submenu.
- buttonToggle.setAttribute( 'aria-expanded', 'true' );
- }
-}
-
-// Necessary for some themes such as TT1 Blocks, where
-// scripts could be loaded before the body.
-window.addEventListener( 'load', () => {
- const submenuButtons = document.querySelectorAll(
- '.wp-block-navigation-submenu__toggle'
- );
-
- submenuButtons.forEach( function ( button ) {
- button.addEventListener( 'click', toggleSubmenuOnClick );
- } );
-
- // Close on click outside.
- document.addEventListener( 'click', function ( event ) {
- const navigationBlocks = document.querySelectorAll(
- '.wp-block-navigation'
- );
- navigationBlocks.forEach( function ( block ) {
- if ( ! block.contains( event.target ) ) {
- closeSubmenus( block );
- }
- } );
- } );
- // Close on focus outside or escape key.
- document.addEventListener( 'keyup', function ( event ) {
- const submenuBlocks = document.querySelectorAll(
- '.wp-block-navigation-item.has-child'
- );
- submenuBlocks.forEach( function ( block ) {
- if ( ! block.contains( event.target ) ) {
- closeSubmenus( block );
- } else if ( event.key === 'Escape' ) {
- const toggle = block.querySelector( '[aria-expanded="true"]' );
- closeSubmenus( block );
- // Focus the submenu trigger so focus does not get trapped in the closed submenu.
- toggle?.focus();
- }
- } );
- } );
-} );
diff --git a/phpunit/blocks/render-block-file-test.php b/phpunit/blocks/render-block-file-test.php
index 7fdeb60a707a9..1dffc320d9671 100644
--- a/phpunit/blocks/render-block-file-test.php
+++ b/phpunit/blocks/render-block-file-test.php
@@ -27,7 +27,13 @@ public function test_render_block_core_file() {
);
$content = '';
- $new_content = gutenberg_render_block_core_file( $attributes, $content );
+ $parsed_blocks = parse_blocks(
+ ''
+ );
+ $parsed_block = $parsed_blocks[0];
+ $block = new WP_Block( $parsed_block );
+
+ $new_content = gutenberg_render_block_core_file( $attributes, $content, $block );
$this->assertStringContainsString( 'aria-label="Embed of yolo."', $new_content );
}
@@ -45,7 +51,13 @@ public function test_render_block_core_file_custom_filename() {
);
$content = '';
- $new_content = gutenberg_render_block_core_file( $attributes, $content );
+ $parsed_blocks = parse_blocks(
+ ''
+ );
+ $parsed_block = $parsed_blocks[0];
+ $block = new WP_Block( $parsed_block );
+
+ $new_content = gutenberg_render_block_core_file( $attributes, $content, $block );
$this->assertStringContainsString( 'aria-label="Embed of custom filename."', $new_content );
}
@@ -63,7 +75,13 @@ public function test_render_block_core_file_empty_filename() {
);
$content = '';
- $new_content = gutenberg_render_block_core_file( $attributes, $content );
+ $parsed_blocks = parse_blocks(
+ ''
+ );
+ $parsed_block = $parsed_blocks[0];
+ $block = new WP_Block( $parsed_block );
+
+ $new_content = gutenberg_render_block_core_file( $attributes, $content, $block );
$this->assertStringContainsString( 'aria-label="PDF embed"', $new_content );
}
}