diff --git a/assets/css/ie.css b/assets/css/ie.css
index 81bfdabca..dd61fff19 100644
--- a/assets/css/ie.css
+++ b/assets/css/ie.css
@@ -5076,7 +5076,7 @@ h1.page-title {
.primary-navigation #toggle-menu {
display: none;
}
- .primary-navigation > .primary-menu-container > ul > li > ul {
+ .primary-navigation > .primary-menu-container ul > li:not(.hover) .sub-menu-toggle[aria-expanded="false"] ~ ul {
display: none;
}
.admin-bar .primary-navigation {
@@ -5112,34 +5112,58 @@ h1.page-title {
margin: 13px 0;
position: relative;
width: 100%;
- z-index: 1;
-}
-
-.primary-navigation > div > .menu-wrapper li:hover, .primary-navigation > div > .menu-wrapper li:focus-within {
- cursor: pointer;
- z-index: 99999;
}
@media only screen and (min-width: 482px) {
.primary-navigation > div > .menu-wrapper li {
- display: inherit;
margin: 0;
width: inherit;
- /* Submenu display in the responsive menu */
- }
- .primary-navigation > div > .menu-wrapper li:hover > ul,
- .primary-navigation > div > .menu-wrapper li:focus-within > ul,
- .primary-navigation > div > .menu-wrapper li ul:hover,
- .primary-navigation > div > .menu-wrapper li ul:focus {
- visibility: visible;
- opacity: 1;
- display: block;
}
.primary-navigation > div > .menu-wrapper li:last-child {
margin-right: 0;
}
}
+.primary-navigation > div > .menu-wrapper .sub-menu-toggle {
+ display: flex;
+ height: 44px;
+ width: 44px;
+ padding: 0;
+ justify-content: center;
+ align-items: center;
+ background: transparent;
+ color: currentColor;
+ border: none;
+}
+
+.primary-navigation > div > .menu-wrapper .sub-menu-toggle:focus {
+ outline: 2px solid #28303d;
+}
+
+@media only screen and (max-width: 481px) {
+ .primary-navigation > div > .menu-wrapper .sub-menu-toggle {
+ display: none;
+ }
+}
+
+.primary-navigation > div > .menu-wrapper .sub-menu-toggle[aria-expanded="false"] {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+}
+
+.primary-navigation > div > .menu-wrapper .sub-menu-toggle[aria-expanded="true"] {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+}
+
+.primary-navigation > div > .menu-wrapper .hover .sub-menu-toggle {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+}
+
.primary-navigation > div > .menu-wrapper > li > .sub-menu {
position: relative;
}
@@ -5150,11 +5174,10 @@ h1.page-title {
left: 0;
margin: 0;
min-width: max-content;
- opacity: 0;
position: absolute;
- top: calc(100% - 13px);
+ top: 100%;
transition: all 0.5s ease;
- visibility: hidden;
+ z-index: 99999;
}
}
diff --git a/assets/js/polyfills.js b/assets/js/polyfills.js
new file mode 100644
index 000000000..0fe666153
--- /dev/null
+++ b/assets/js/polyfills.js
@@ -0,0 +1,41 @@
+/**
+ * File primary-navigation.js.
+ *
+ * Required to open and close the mobile navigation.
+ */
+
+/**
+ * Polyfill for Element.closest() because we need to support IE11.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
+ */
+if ( ! Element.prototype.matches ) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+}
+
+if ( ! Element.prototype.closest ) {
+ Element.prototype.closest = function( s ) {
+ var el = this;
+ do {
+ if ( Element.prototype.matches.call( el, s ) ) {
+ return el;
+ }
+ el = el.parentElement || el.parentNode;
+ } while ( el !== null && el.nodeType === 1 );
+ return null;
+ };
+}
+
+/**
+ * Polyfill for NodeList.foreach() because we need to support IE11.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
+ */
+if ( window.NodeList && ! NodeList.prototype.forEach ) {
+ NodeList.prototype.forEach = function( callback, thisArg ) {
+ thisArg = thisArg || window;
+ for ( var i = 0; i < this.length; i++ ) {
+ callback.call( thisArg, this[i], i, this );
+ }
+ };
+}
diff --git a/assets/js/primary-navigation.js b/assets/js/primary-navigation.js
index 44365ce9e..5ea77926d 100644
--- a/assets/js/primary-navigation.js
+++ b/assets/js/primary-navigation.js
@@ -3,30 +3,63 @@
*
* Required to open and close the mobile navigation.
*/
-( function() {
- /**
- * Toggle an attribute's value
- *
- * @param {Element} element
- * @param {Attribute} attribute
- * @param {String} trueVal
- * @param {String} falseVal
- * @since 1.0.0
- */
- var toggleAttribute = function ( element, attribute, trueVal, falseVal ) {
- if ( undefined === trueVal ) {
- trueVal = true;
- }
- if ( undefined === falseVal ) {
- falseVal = false;
+/**
+ * Toggle an attribute's value
+ *
+ * @param {Element} el - The element.
+ * @since 1.0.0
+ */
+function twentytwentyoneToggleAriaExpanded( el, withListeners ) {
+ if ( 'true' !== el.getAttribute( 'aria-expanded' ) ) {
+ el.setAttribute( 'aria-expanded', 'true' );
+ if ( withListeners ) {
+ document.addEventListener( 'click', twentytwentyoneCollapseMenuOnClickOutside );
}
- if ( trueVal !== element.getAttribute( attribute ) ) {
- element.setAttribute( attribute, trueVal );
- } else {
- element.setAttribute( attribute, falseVal );
+ } else {
+ el.setAttribute( 'aria-expanded', 'false' );
+ if ( withListeners ) {
+ document.removeEventListener( 'click', twentytwentyoneCollapseMenuOnClickOutside );
}
}
+}
+
+function twentytwentyoneCollapseMenuOnClickOutside( event ) {
+ if ( ! document.getElementById( 'site-navigation' ).contains( event.target ) ) {
+ document.getElementById( 'site-navigation' ).querySelectorAll( '.sub-menu-toggle' ).forEach( function( button ) {
+ button.setAttribute( 'aria-expanded', 'false' );
+ } );
+ }
+}
+
+/**
+ * Handle clicks on submenu toggles.
+ *
+ * @param {Element} el - The element.
+ */
+function twentytwentyoneExpandSubMenu( el ) {
+
+ // Close other expanded items.
+ el.closest( 'nav' ).querySelectorAll( '.sub-menu-toggle' ).forEach( function( button ) {
+ if ( button !== el ) {
+ button.setAttribute( 'aria-expanded', 'false' );
+ }
+ } );
+
+ // Toggle aria-expanded on the button.
+ twentytwentyoneToggleAriaExpanded( el, true );
+
+ // On tab-away collapse the menu.
+ el.parentNode.querySelectorAll( 'ul > li:last-child > a' ).forEach( function( linkEl ) {
+ linkEl.addEventListener( 'blur', function( event ) {
+ if ( ! el.parentNode.contains( event.relatedTarget ) ) {
+ el.setAttribute( 'aria-expanded', 'false' );
+ }
+ } );
+ } );
+}
+
+( function() {
/**
* Menu Toggle Behaviors
@@ -34,27 +67,26 @@
* @param {Element} element
*/
var navMenu = function ( id ){
- var wrapper = document.body; // this is the element to which a CSS class is added when a mobile nav menu is open
- var mobileButton = document.getElementById( `${ id }-mobile-menu` );
+ var wrapper = document.body, // this is the element to which a CSS class is added when a mobile nav menu is open
+ mobileButton = document.getElementById( `${ id }-mobile-menu` );
if ( mobileButton ){
mobileButton.onclick = function() {
wrapper.classList.toggle( `${ id }-navigation-open` );
wrapper.classList.toggle( 'lock-scrolling' );
- toggleAttribute( mobileButton, 'aria-expanded', 'true', 'false' );
+ twentytwentyoneToggleAriaExpanded( mobileButton );
mobileButton.focus();
}
}
-
/**
* Trap keyboard navigation in the menu modal.
* Adapted from TwentyTwenty
*/
document.addEventListener( 'keydown', function( event ) {
+ var modal, elements, selectors, lastEl, firstEl, activeEl, tabKey, shiftKey, escKey;
if ( ! wrapper.classList.contains( `${ id }-navigation-open` ) ){
return;
- }
- var modal, elements, selectors, lastEl, firstEl, activeEl, tabKey, shiftKey, escKey;
+ }
modal = document.querySelector( `.${ id }-navigation` );
selectors = "input, a, button";
@@ -70,7 +102,7 @@
if ( escKey ) {
event.preventDefault();
wrapper.classList.remove( `${ id }-navigation-open`, 'lock-scrolling' );
- toggleAttribute( mobileButton, 'aria-expanded', 'true', 'false' );
+ twentytwentyoneToggleAriaExpanded( mobileButton );
mobileButton.focus();
}
@@ -88,10 +120,19 @@
if ( tabKey && firstEl === lastEl ) {
event.preventDefault();
}
- });
+ } );
+
+ document.getElementById( 'site-navigation' ).querySelectorAll( '.menu-wrapper > .menu-item-has-children' ).forEach( function( li ) {
+ li.addEventListener( 'mouseenter', function() {
+ this.classList.add( 'hover' );
+ } );
+ li.addEventListener( 'mouseleave', function() {
+ this.classList.remove( 'hover' );
+ } );
+ } );
}
window.addEventListener( 'load', function() {
new navMenu( 'primary' );
});
-} )();
\ No newline at end of file
+} )();
diff --git a/assets/sass/06-components/navigation.scss b/assets/sass/06-components/navigation.scss
index 5c25498b9..5230a9725 100644
--- a/assets/sass/06-components/navigation.scss
+++ b/assets/sass/06-components/navigation.scss
@@ -162,7 +162,7 @@
}
// Hide sub-sub-menus
- > .primary-menu-container > ul > li > ul {
+ > .primary-menu-container ul > li:not(.hover) .sub-menu-toggle[aria-expanded="false"] ~ ul {
display: none;
}
@@ -200,35 +200,59 @@
margin: var(--primary-nav--padding) 0;
position: relative;
width: 100%;
- z-index: 1;
-
- &:hover,
- &:focus-within {
- cursor: pointer;
- z-index: 99999;
- }
@include media(mobile) {
- display: inherit;
margin: 0;
width: inherit;
- /* Submenu display in the responsive menu */
- &:hover > ul,
- &:focus-within > ul,
- ul:hover,
- ul:focus {
- visibility: visible;
- opacity: 1;
- display: block;
- }
-
&:last-child() {
margin-right: 0;
}
}
}
+ // Sub-menu buttons
+ .sub-menu-toggle {
+ display: flex;
+ height: 44px;
+ width: 44px;
+ padding: 0;
+ justify-content: center;
+ align-items: center;
+ background: transparent;
+ color: currentColor;
+ border: none;
+
+ &:focus {
+ outline: 2px solid var(--wp--style--color--link, var(--global--color-primary));
+ }
+
+ @include media(mobile-only) {
+ display: none;
+ }
+
+ // When the sub-menu is closed, display the plus icon
+ &[aria-expanded="false"] {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+ }
+
+ // When the sub-menu is open, display the minus icon
+ &[aria-expanded="true"] {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+ }
+
+ }
+
+ .hover .sub-menu-toggle {
+ /* stylelint-disable */
+ background: url("data:image/svg+xml;utf8,") no-repeat center center;
+ /* stylelint-enable */
+ }
+
// Sub-menus Flyout
> li > .sub-menu {
@@ -239,11 +263,10 @@
left: 0;
margin: 0;
min-width: max-content;
- opacity: 0;
position: absolute;
- top: calc(100% - var(--primary-nav--padding));
+ top: 100%;
transition: all 0.5s ease;
- visibility: hidden;
+ z-index: 99999;
}
.sub-menu {
@@ -315,7 +338,7 @@
list-style: none;
margin-left: var(--primary-nav--padding);
- // Sub menu items om wide screens.
+ // Sub-menu items om wide screens.
@include media(mobile) {
padding: 0 var(--primary-nav--padding);
diff --git a/classes/class-twenty-twenty-one-svg-icons.php b/classes/class-twenty-twenty-one-svg-icons.php
index 57c5b4dbb..69eeb28e9 100644
--- a/classes/class-twenty-twenty-one-svg-icons.php
+++ b/classes/class-twenty-twenty-one-svg-icons.php
@@ -62,7 +62,5 @@ public static function get_svg( $group, $icon, $size ) {
'arrow_left' => '',
'close' => '',
'menu' => '',
- 'minus' => '',
- 'plus' => '',
);
}
diff --git a/functions.php b/functions.php
index 3a96ba250..263b80cb3 100644
--- a/functions.php
+++ b/functions.php
@@ -350,7 +350,20 @@ function twenty_twenty_one_scripts() {
// Main navigation scripts.
if ( has_nav_menu( 'primary' ) ) {
- wp_enqueue_script( 'twenty-twenty-one-primary-navigation-script', get_template_directory_uri() . '/assets/js/primary-navigation.js', array(), wp_get_theme()->get( 'Version' ), true );
+ wp_register_script(
+ 'twenty-twenty-one-ie11-polyfills',
+ get_template_directory_uri() . '/assets/js/polyfills.js',
+ array(),
+ wp_get_theme()->get( 'Version' ),
+ true
+ );
+ wp_enqueue_script(
+ 'twenty-twenty-one-primary-navigation-script',
+ get_template_directory_uri() . '/assets/js/primary-navigation.js',
+ array( 'twenty-twenty-one-ie11-polyfills' ),
+ wp_get_theme()->get( 'Version' ),
+ true
+ );
}
}
add_action( 'wp_enqueue_scripts', 'twenty_twenty_one_scripts' );
diff --git a/header.php b/header.php
index 1208ee030..6b8e7472b 100644
--- a/header.php
+++ b/header.php
@@ -30,9 +30,9 @@
-