Skip to content

Commit

Permalink
Header: Switch to submenu blocks for navigation items with submenus
Browse files Browse the repository at this point in the history
Fixes #207
  • Loading branch information
ryelle committed Jun 16, 2022
1 parent 054f240 commit 889a7b8
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 47 deletions.
77 changes: 44 additions & 33 deletions mu-plugins/blocks/global-header-footer/header.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

namespace WordPressdotorg\MU_Plugins\Global_Header_Footer\Header;

use function WordPressdotorg\MU_Plugins\Global_Header_Footer\{ get_home_url, get_download_url };

defined( 'WPINC' ) || die();
Expand All @@ -26,6 +27,45 @@
'formAction' => 'https://wordpress.org/search/do-search.php',
);

/**
* Ouput menu items (`navigation-link`) & submenus (`navigation-submenu`). If a submenu, recursively iterate
* through submenu items to output links.
*
* @param array $menu_item An item from the array in `get_global_menu_items` or `get_rosetta_menu_items`.
* @param boolean $top_level Whether the menu item is a top-level link.
* @return string
*/
function recursive_menu( $menu_item, $top_level = true ) {
$has_submenu = ! empty( $menu_item['submenu'] );

if ( ! $has_submenu ) {
return sprintf(
'<!-- wp:navigation-link {"label":"%1$s","url":"%2$s","kind":"%3$s","isTopLevelLink":%4$s,"className":"%5$s"} /-->',
$menu_item['title'],
$menu_item['url'],
$menu_item['type'],
$top_level ? 'true' : 'false',
$menu_item['classes'] ?? '',
);
}

$ouput = sprintf(
'<!-- wp:navigation-submenu {"label":"%1$s","url":"%2$s","kind":"%3$s","className":"%4$s"} -->',
$menu_item['title'],
$menu_item['url'],
$menu_item['type'],
$menu_item['classes'] ?? '',
);

foreach ( $menu_item['submenu'] as $submenu_item ) {
$ouput .= recursive_menu( $submenu_item, false );
}

$ouput .= '<!-- /wp:navigation-submenu -->';

return $ouput;
}

?>

<!-- wp:group {"tagName":"header","align":"full","className":"<?php echo esc_attr( $container_class ); ?>"} -->
Expand Down Expand Up @@ -53,44 +93,15 @@
<!-- /wp:paragraph -->
<?php endif; ?>

<!-- wp:navigation {"orientation":"horizontal","className":"global-header__navigation","overlayMenu":"mobile"} -->
<!-- wp:navigation {"orientation":"horizontal","className":"global-header__navigation","overlayMenu":"mobile","openSubmenusOnClick":false} -->
<?php

/*
* Loop though menu items and create `navigation-link` block comments.
*
* This only supports 1 level deep, but that's currently enough for our needs. More than that could be an
* information architecture smell anyways.
* Loop though menu items and create navigation item blocks. Recurses through any submenu items to output dropdowns.
*/
foreach ( $menu_items as $item ) {
$is_top_level_link = empty( $item['submenu'] );

printf(
'<!-- wp:navigation-link {"label":"%s","url":"%s","kind":"%s","isTopLevelLink":%s,"className":"%s"} %s-->',
// These sometimes come from user input (like with Rosetta menus), but `render_block_core_navigation_link()` will escape the values.
$item['title'],
$item['url'],
$item['type'],
json_encode( $is_top_level_link ),
$item['classes'] ?? '',
$is_top_level_link ? '/' : ''
);

if ( ! $is_top_level_link ) {
foreach( $item['submenu'] as $submenu_item ) {
printf(
'<!-- wp:navigation-link {"label":"%s","url":"%s","kind":"%s","isTopLevelLink":true,"className":"%s"} /-->',
$submenu_item['title'],
$submenu_item['url'],
$submenu_item['type'],
$submenu_item['classes'] ?? '',
);
}

echo '<!-- /wp:navigation-link -->';
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo recursive_menu( $item );
}

?>
<!-- /wp:navigation -->

Expand Down
115 changes: 101 additions & 14 deletions mu-plugins/blocks/global-header-footer/postcss/header/menu.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@

& svg {
fill: none;
stroke: currentColor;
stroke: currentcolor;
}
}
}
Expand Down Expand Up @@ -226,39 +226,106 @@
}
}

/*
Copied Gutenberg styles to provide broader browser support.
The code below is only applied via CSS :where selector in default Gutenberg styles.
See: https://github.com/WordPress/wporg-mu-plugins/issues/159
*/

& .wp-block-navigation__container {

@media (--tablet) {
background: var(--wp--preset--color--dark-grey);
}
}
}

/*
Copied Gutenberg styles to provide broader browser support.
The code below is only applied via CSS :where selector in default Gutenberg styles.
& .wp-block-navigation .has-child .wp-block-navigation__submenu-container {
See: https://github.com/WordPress/wporg-mu-plugins/issues/159
Source: https://github.com/WordPress/gutenberg/blob/3b2eccc289cfc90bd99252b12fc4c6e470ce4c04/packages/block-library/src/navigation/style.scss#L157
*/

.wp-block-navigation .has-child {
& .wp-block-navigation__submenu-container {
background-color: inherit;
color: inherit;
position: absolute;
z-index: 2;
display: flex;
flex-direction: column;
align-items: normal;

/* Hide until hover or focus within. */
opacity: 0;
transition: opacity 0.1s linear;
visibility: hidden;

/* Don't take up space when the menu is collapsed. */
width: 0;
height: 0;
overflow: hidden;
left: -1px;
overflow: hidden; /* Overflow is necessary to set, otherwise submenu items will take up space. */

/* Submenu items. */
& > .wp-block-navigation-item {
& > .wp-block-navigation-item__content {
display: flex;
flex-grow: 1;

/* Right-align the chevron in submenus. */
& .wp-block-navigation__submenu-icon {
margin-right: 0;
margin-left: auto;
}
}
}

/* Spacing in all submenus. */
& .wp-block-navigation-item__content {
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.
*/

@media (--tablet) {
& .wp-block-navigation__submenu-container {
left: 100%;
top: -1px; /* Border width. */

/* Prevent the menu from disappearing when the mouse is over the gap */
&::before {
content: "";
position: absolute;
right: 100%;
height: 100%;
display: block;
width: 0.5em;
background: transparent;
}
}

/* Push inwards from right edge of submenu. */
& .wp-block-navigation__submenu-icon {
margin-right: 0.25em;
}

/* Reset the submenu indicator for horizontal flyouts. */
& .wp-block-navigation__submenu-icon svg {
transform: rotate(-90deg);
}
}
}

& .wp-block-navigation .has-child:focus-within > .wp-block-navigation__submenu-container,
& .wp-block-navigation .has-child:hover > .wp-block-navigation__submenu-container {
/*
* 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;
Expand All @@ -267,9 +334,29 @@
min-width: 200px;
}

/* End :where fix */
/* 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;
}
}

/* End :where fix */

/* Gutenberg bug: Close button is not visible in Safari; override it locally */
.global-header__navigation .is-menu-open {
overflow: visible;
Expand Down

0 comments on commit 889a7b8

Please sign in to comment.