diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php
index f4d56465ea8ccc..bfc428c8914e24 100644
--- a/packages/block-library/src/navigation/index.php
+++ b/packages/block-library/src/navigation/index.php
@@ -811,7 +811,9 @@ function block_core_navigation_add_directives_to_submenu( $tags, $block_attribut
// Add directives to the parent `
`.
$tags->set_attribute( 'data-wp-interactive', 'core/navigation' );
$tags->set_attribute( 'data-wp-context', '{ "submenuOpenedBy": { "click": false, "hover": false, "focus": false }, "type": "submenu", "modal": null }' );
- $tags->set_attribute( 'data-wp-on--focusout', 'actions.handleMenuFocusout' );
+ // TODO: Check if this is intended. Before this was on the submenu container, but then caused it to never open from focus alone.
+ $tags->set_attribute( 'data-wp-on--focusin', 'actions.openMenuOnFocus' );
+ $tags->set_attribute( 'data-wp-on--focusout', 'actions.closeMenuOnFocus' );
$tags->set_attribute( 'style', "anchor-name: --{$anchor_name};" );
// This is a fix for Safari. Without it, Safari doesn't change the active
@@ -847,9 +849,9 @@ function block_core_navigation_add_directives_to_submenu( $tags, $block_attribut
$id = $anchor_name;
$tags->set_attribute( 'id', $id );
}
- $tags->set_attribute( 'popover', isset( $block_attributes['openSubmenusOnClick'] ) && $block_attributes['openSubmenusOnClick'] ? 'auto' : 'hint' );
+ // TODO: `popover=hint` is not supported yet, but eventually it should be used if the menu opens on hover.
+ $tags->set_attribute( 'popover', /* isset( $block_attributes['openSubmenusOnClick'] ) && $block_attributes['openSubmenusOnClick'] ? 'auto' : 'hint' */ 'auto' );
$tags->set_attribute( 'data-wp-on--toggle', 'actions.handleToggle' );
- $tags->set_attribute( 'data-wp-on-async--focus', 'actions.openMenuOnFocus' );
$tags->set_attribute( 'data-wp-watch', 'callbacks.setModal' );
$tags->set_attribute( 'style', "position-anchor: --{$anchor_name};" );
diff --git a/packages/block-library/src/navigation/style.scss b/packages/block-library/src/navigation/style.scss
index e293b37f4ebaf1..d57125114a708b 100644
--- a/packages/block-library/src/navigation/style.scss
+++ b/packages/block-library/src/navigation/style.scss
@@ -159,6 +159,12 @@ $navigation-icon-size: 24px;
background-color: inherit;
color: inherit;
position: absolute;
+ margin: 0;
+ padding: 0;
+ right: auto;
+ left: anchor(left);
+ top: anchor(bottom);
+ bottom: auto;
display: flex;
flex-direction: column;
align-items: normal;
@@ -170,18 +176,21 @@ $navigation-icon-size: 24px;
}
visibility: hidden;
+ // Submenu indentation when there's no background.
+ margin-left: -1px; // Border width.
+
// Don't take up space when the menu is collapsed.
width: 0;
height: 0;
overflow: hidden; // Overflow is necessary to set, otherwise submenu items will take up space.
- &[popover] {
- margin: 0;
- padding: 0;
- right: auto;
- left: anchor(left);
- top: anchor(bottom);
- bottom: auto;
+ &:popover-open {
+ visibility: visible;
+ overflow: visible;
+ opacity: 1;
+ width: auto;
+ height: auto;
+ min-width: 200px;
}
// Submenu items.
@@ -203,16 +212,11 @@ $navigation-icon-size: 24px;
margin: 0;
}
- // Submenu indentation when there's no background.
- left: -1px; // Border width.
- top: 100%;
-
// Indentation for all submenus.
// Nested submenus sit to the left on large breakpoints.
// On smaller breakpoints, they open vertically, accordion-style.
@include break-medium {
.wp-block-navigation__submenu-container {
- left: 100%;
top: -1px; // Border width.
// Prevent the menu from disappearing when the mouse is over the gap
@@ -238,50 +242,17 @@ $navigation-icon-size: 24px;
}
}
}
-
- // Custom menu items.
- // Show submenus on hover unless they open on click.
- &:not(.open-on-click):hover > .wp-block-navigation__submenu-container {
- visibility: visible;
- overflow: visible;
- opacity: 1;
- width: auto;
- height: auto;
- min-width: 200px;
- }
-
- // Keep submenus open when focus is within.
- &:not(.open-on-click):not(.open-on-hover-click):focus-within > .wp-block-navigation__submenu-container {
- visibility: visible;
- overflow: visible;
- opacity: 1;
- width: auto;
- height: auto;
- min-width: 200px;
- }
-
- // Show submenus on click.
- .wp-block-navigation-submenu__toggle[aria-expanded="true"] ~ .wp-block-navigation__submenu-container {
- visibility: visible;
- overflow: visible;
- opacity: 1;
- width: auto;
- height: auto;
- min-width: 200px;
- }
}
// Submenu indentation when there's a background.
.wp-block-navigation.has-background
.has-child
.wp-block-navigation__submenu-container {
- left: 0;
- top: 100%;
+ margin-left: 0;
// There's no border on submenus when there are backgrounds.
@include break-medium {
.wp-block-navigation__submenu-container {
- left: 100%;
top: 0;
}
}
@@ -392,12 +363,7 @@ button.wp-block-navigation-item__content {
// First submenu.
.wp-block-navigation__submenu-container {
left: auto;
- right: 0;
-
- &[popover] {
- left: auto;
- right: anchor(right);
- }
+ right: anchor(right);
// Nested submenus.
// On smaller breakpoints, nested menus open downwards.
diff --git a/packages/block-library/src/navigation/view.js b/packages/block-library/src/navigation/view.js
index 28c9589e059009..faafa79da30fea 100644
--- a/packages/block-library/src/navigation/view.js
+++ b/packages/block-library/src/navigation/view.js
@@ -66,6 +66,7 @@ const { state, actions } = store(
actions.openMenu( 'hover' );
}
},
+
closeMenuOnHover() {
const { type, overlayOpenedBy } = getContext();
if (
@@ -77,12 +78,37 @@ const { state, actions } = store(
actions.closeMenu( 'hover' );
}
},
+
openMenuOnFocus() {
const { type } = getContext();
+ window.console.log( 'openMenuOnFocus', type );
if ( type === 'submenu' ) {
actions.openMenu( 'focus' );
}
},
+
+ closeMenuOnFocus( event ) {
+ const { modal, type } = getContext();
+ window.console.log( 'closeMenuOnFocus', type );
+ // If focus is outside modal, and in the document, close menu
+ // event.target === The element losing focus
+ // event.relatedTarget === The element receiving focus (if any)
+ // When focusout is outside the document,
+ // `window.document.activeElement` doesn't change.
+
+ // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
+ // TODO: Double-check this change here. See https://github.com/WordPress/gutenberg/pull/60406#issuecomment-2641303669.
+ if (
+ type === 'submenu' &&
+ ( event.relatedTarget === null ||
+ ( ! modal?.contains( event.relatedTarget ) &&
+ event.target !== window.document.activeElement ) )
+ ) {
+ actions.closeMenu( 'click' );
+ actions.closeMenu( 'focus' );
+ }
+ },
+
toggleMenuOnClick() {
const ctx = getContext();
if ( ctx.type === 'submenu' ) {
@@ -101,6 +127,7 @@ const { state, actions } = store(
}
}
},
+
handleMenuKeydown( event ) {
const { type, firstFocusableElement, lastFocusableElement } =
getContext();
@@ -126,26 +153,6 @@ const { state, actions } = store(
}
}
},
- handleMenuFocusout( event ) {
- const { modal, type } = getContext();
- // If focus is outside modal, and in the document, close menu
- // event.target === The element losing focus
- // event.relatedTarget === The element receiving focus (if any)
- // When focusout is outside the document,
- // `window.document.activeElement` doesn't change.
-
- // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
- // TODO: Double-check this change here. See https://github.com/WordPress/gutenberg/pull/60406#issuecomment-2641303669.
- if (
- type === 'submenu' &&
- ( event.relatedTarget === null ||
- ( ! modal?.contains( event.relatedTarget ) &&
- event.target !== window.document.activeElement ) )
- ) {
- actions.closeMenu( 'click' );
- actions.closeMenu( 'focus' );
- }
- },
handleToggle( event ) {
const ctx = getContext();
@@ -192,14 +199,14 @@ const { state, actions } = store(
openMenu( menuOpenedOn = 'click' ) {
const ctx = getContext();
- window.console.log( 'openMenu', ctx.modal );
+ //window.console.log( 'openMenu', ctx.modal );
state.menuOpenedBy[ menuOpenedOn ] = true;
ctx.modal?.showPopover();
},
closeMenu( menuClosedOn = 'click' ) {
const ctx = getContext();
- window.console.log( 'closeMenu', ctx.modal );
+ //window.console.log( 'closeMenu', ctx.modal );
state.menuOpenedBy[ menuClosedOn ] = false;
// Check if the menu is still open or not.
if ( ! state.isMenuOpen ) {