feat: add submenu opt-in for main navigation
This commit is contained in:
parent
204d05b6d7
commit
d9a5b018af
8 changed files with 280 additions and 55 deletions
|
|
@ -68,7 +68,8 @@ export const navigation = {
|
||||||
ariaTop: 'Main',
|
ariaTop: 'Main',
|
||||||
ariaBottom: 'Complementary',
|
ariaBottom: 'Complementary',
|
||||||
ariaPlatforms: 'Platforms',
|
ariaPlatforms: 'Platforms',
|
||||||
drawerNav: false
|
drawerNav: false,
|
||||||
|
subMenu: false
|
||||||
};
|
};
|
||||||
export const themeSwitch = {
|
export const themeSwitch = {
|
||||||
title: 'Theme',
|
title: 'Theme',
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,49 @@
|
||||||
<!-- toggle drawer menu in _data/meta.js -->
|
<!-- toggle drawer and sub menu in _data/meta.js -->
|
||||||
{% set drawerNav = meta.navigation.drawerNav %}
|
{% set drawerNav = meta.navigation.drawerNav %}
|
||||||
|
{% set subMenu = meta.navigation.subMenu %}
|
||||||
|
|
||||||
<nav id="mainnav" class="mainnav" aria-label="{{ meta.navigation.ariaTop }}">
|
<nav id="mainnav" class="mainnav" aria-label="{{ meta.navigation.ariaTop }}">
|
||||||
<ul class="cluster" role="list" no-flash>
|
<ul class="cluster" role="list" no-flash>
|
||||||
{% for item in navigation.top %}
|
{% for item in navigation.top %}
|
||||||
<li>
|
{% if item.submenu %}
|
||||||
<a
|
<li class="relative">
|
||||||
href="{{ item.url }}"
|
<button
|
||||||
{{
|
data-submenu-toggle
|
||||||
helpers.getLinkActiveState(item.url,
|
aria-expanded="false"
|
||||||
page.url)
|
aria-labelledby="mainnav-{{ loop.index }}"
|
||||||
|
|
aria-controls="mainnav-{{ loop.index }}-sub"
|
||||||
safe
|
>
|
||||||
}}
|
{{ item.text }} {% svg "misc/chev-down" %}
|
||||||
>{{ item.text }}</a
|
</button>
|
||||||
>
|
<ul class="nav-sublist | cluster" id="mainnav-{{ loop.index }}-sub">
|
||||||
</li>
|
{% for subitem in item.submenu %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ subitem.url }}"
|
||||||
|
{{
|
||||||
|
helpers.getLinkActiveState(subitem.url, page.url)
|
||||||
|
| safe
|
||||||
|
}}
|
||||||
|
>{{ subitem.text }}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ item.url }}"
|
||||||
|
{{
|
||||||
|
helpers.getLinkActiveState(item.url,
|
||||||
|
page.url)
|
||||||
|
|
|
||||||
|
safe
|
||||||
|
}}
|
||||||
|
>{{ item.text }}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@ -26,7 +54,7 @@
|
||||||
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
|
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
|
||||||
|
|
||||||
<template id="burger-template">
|
<template id="burger-template">
|
||||||
<button type="button" aria-expanded="false" aria-controls="mainnav" class="cluster">
|
<button data-drawer-toggle class="cluster" type="button" aria-expanded="false" aria-controls="mainnav">
|
||||||
<span>{{ meta.navigation.navLabel }}</span>
|
<span>{{ meta.navigation.navLabel }}</span>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -44,9 +72,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if drawerNav %}
|
|
||||||
{% css "local" %}
|
{% css "local" %}
|
||||||
{% include "css/nav-main-drawer-cls.css" %}
|
{% include "css/nav-main-drawer-cls.css" %}
|
||||||
{% endcss %}
|
{% endcss %}
|
||||||
|
|
@ -55,3 +81,9 @@
|
||||||
{% include "scripts/nav-drawer.js" %}
|
{% include "scripts/nav-drawer.js" %}
|
||||||
{% endjs %}
|
{% endjs %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if subMenu %}
|
||||||
|
{% js "defer" %}
|
||||||
|
{% include "scripts/nav-sub.js" %}
|
||||||
|
{% endjs %}
|
||||||
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav:has([aria-expanded='true']) {
|
.mainnav:has([data-drawer-toggle][aria-expanded='true']) {
|
||||||
--nav-position: fixed;
|
--nav-position: fixed;
|
||||||
inset-inline-end: var(--gap);
|
inset-inline-end: var(--gap);
|
||||||
}
|
}
|
||||||
|
|
@ -13,11 +13,13 @@
|
||||||
/* configuration */
|
/* configuration */
|
||||||
--gutter: var(--space-xs);
|
--gutter: var(--space-xs);
|
||||||
--cluster-vertical-alignment: normal;
|
--cluster-vertical-alignment: normal;
|
||||||
|
--cluster-wrap: wrap;
|
||||||
|
--cluster-direction: column;
|
||||||
--nav-list-background: var(--color-bg);
|
--nav-list-background: var(--color-bg);
|
||||||
--nav-list-shadow: -5px 0 11px 0 hsl(0 0% 0% / 0.2);
|
--nav-list-shadow: -5px 0 11px 0 hsl(0 0% 0% / 0.2);
|
||||||
--nav-list-layout: column;
|
|
||||||
--nav-list-height: 100dvh;
|
--nav-list-height: 100dvh;
|
||||||
--nav-list-padding: var(--space-2xl) var(--space-s);
|
--nav-list-padding-block: var(--space-2xl);
|
||||||
|
--nav-list-padding-inline: var(--space-s);
|
||||||
--nav-list-position: fixed;
|
--nav-list-position: fixed;
|
||||||
--nav-list-width: min(18rem, 100vw);
|
--nav-list-width: min(18rem, 100vw);
|
||||||
--nav-list-visibility: hidden;
|
--nav-list-visibility: hidden;
|
||||||
|
|
@ -25,13 +27,11 @@
|
||||||
|
|
||||||
background: var(--nav-list-background);
|
background: var(--nav-list-background);
|
||||||
box-shadow: var(--nav-list-shadow);
|
box-shadow: var(--nav-list-shadow);
|
||||||
display: flex;
|
|
||||||
flex-direction: var(--nav-list-layout);
|
|
||||||
flex-wrap: wrap;
|
|
||||||
block-size: var(--nav-list-height);
|
block-size: var(--nav-list-height);
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: var(--nav-list-padding);
|
padding-block: var(--nav-list-padding-block);
|
||||||
|
padding-inline: var(--nav-list-padding-inline);
|
||||||
position: var(--nav-list-position);
|
position: var(--nav-list-position);
|
||||||
inset-block-start: 0;
|
inset-block-start: 0;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
.mainnav ul {
|
.mainnav > ul {
|
||||||
--nav-list-transform: translateX(100%);
|
--nav-list-transform: translateX(100%);
|
||||||
--nav-list-opacity: 1;
|
--nav-list-opacity: 1;
|
||||||
transform: var(--nav-list-transform);
|
transform: var(--nav-list-transform);
|
||||||
|
|
@ -62,22 +62,29 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav [aria-expanded='true'] + ul {
|
.mainnav [data-drawer-toggle] {
|
||||||
--nav-list-visibility: visible;
|
|
||||||
--nav-list-transform: translateX(0);
|
|
||||||
--nav-list-opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mainnav button {
|
|
||||||
--gutter: var(--space-2xs);
|
--gutter: var(--space-2xs);
|
||||||
--cluster-vertical-alignment: center;
|
--cluster-vertical-alignment: center;
|
||||||
display: var(--nav-button-display, flex);
|
background: var(--color-bg);
|
||||||
|
display: var(--nav-button-display, inline-flex);
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
padding: var(--space-2xs) 0;
|
padding: var(--space-2xs) 0;
|
||||||
line-height: var(--leading-flat);
|
line-height: var(--leading-flat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mainnav [data-drawer-toggle][aria-expanded='true'] + ul {
|
||||||
|
--cluster-wrap: nowrap;
|
||||||
|
--nav-list-visibility: visible;
|
||||||
|
--nav-list-transform: translateX(0);
|
||||||
|
--nav-list-opacity: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has([data-drawer-toggle][aria-expanded='true']) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.mainnav span {
|
.mainnav span {
|
||||||
font-weight: var(--font-bold);
|
font-weight: var(--font-bold);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
@ -95,15 +102,18 @@
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav a {
|
.mainnav :is(a, [data-submenu-toggle]) {
|
||||||
/* configuration */
|
/* configuration */
|
||||||
--nav-item-background: transparent;
|
--nav-item-background: transparent;
|
||||||
--nav-item-text-color: var(--color-text);
|
--nav-item-text-color: var(--color-text);
|
||||||
--nav-item-padding: var(--space-xs) var(--space-2xs);
|
--nav-item-padding: var(--space-xs) var(--space-2xs);
|
||||||
--nav-item-decoration-color: transparent;
|
--nav-item-decoration-color: transparent;
|
||||||
|
--nav-item-font-size: var(--size-step-0);
|
||||||
|
--nav-item-font-weight: var(--font-bold);
|
||||||
|
|
||||||
background: var(--nav-item-background);
|
background: var(--nav-item-background);
|
||||||
color: var(--nav-item-text-color);
|
color: var(--nav-item-text-color);
|
||||||
|
font-size: var(--nav-item-font-size);
|
||||||
padding: var(--nav-item-padding);
|
padding: var(--nav-item-padding);
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: var(--border-radius-medium);
|
border-radius: var(--border-radius-medium);
|
||||||
|
|
@ -113,17 +123,68 @@
|
||||||
text-underline-offset: 0.2em;
|
text-underline-offset: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav a:where(:hover, :focus) {
|
.mainnav:has(.nav-sublist) :is(a, [data-submenu-toggle]) {
|
||||||
|
font-weight: var(--nav-item-font-weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav [data-submenu-toggle] {
|
||||||
|
gap: var(--space-2xs);
|
||||||
|
display: flex;
|
||||||
|
inline-size: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav [data-submenu-toggle] svg {
|
||||||
|
margin-inline-end: calc(var(--gap) - var(--nav-list-padding-inline));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav :is(a, [data-submenu-toggle]):hover {
|
||||||
--nav-item-background: transparent;
|
--nav-item-background: transparent;
|
||||||
--nav-item-text-color: var(--color-text);
|
--nav-item-text-color: var(--color-text);
|
||||||
--nav-item-decoration-color: var(--color-text);
|
--nav-item-decoration-color: var(--color-bg-accent-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav [aria-current='page'],
|
.mainnav [aria-current='page'],
|
||||||
.mainnav [data-state='active'] {
|
.mainnav [data-state='active'] {
|
||||||
--nav-item-background: var(--color-primary);
|
--nav-item-background: var(--color-bg);
|
||||||
--nav-item-text-color: var(--color-light);
|
--nav-item-text-color: var(--color-primary);
|
||||||
--nav-item-decoration-color: transparent;
|
--nav-item-decoration-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* current parent (if submenu) */
|
||||||
|
li:has(ul a[aria-current='page']) > [data-submenu-toggle] {
|
||||||
|
--nav-item-background: var(--color-bg);
|
||||||
|
--nav-item-text-color: var(--color-text);
|
||||||
|
--nav-item-decoration-color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sub menu */
|
||||||
|
|
||||||
|
.mainnav [data-submenu-toggle][aria-expanded='false'] + ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav .nav-sublist {
|
||||||
|
--gutter: 0;
|
||||||
|
--cluster-direction: column;
|
||||||
|
--nav-sublist-position: relative;
|
||||||
|
--nav-sublist-background: var(--color-bg);
|
||||||
|
--nav-sublist-width: 100%;
|
||||||
|
--nav-list-visibility: visible;
|
||||||
|
--nav-list-opacity: 1;
|
||||||
|
--nav-list-padding-block: 0 var(--space-m);
|
||||||
|
--nav-list-padding-inline: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
position: var(--nav-sublist-position);
|
||||||
|
inline-size: var(--nav-sublist-width);
|
||||||
|
block-size: auto;
|
||||||
|
background: var(--nav-sublist-background);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav .nav-sublist a {
|
||||||
|
--nav-item-font-weight: var(--font-regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen(navigation) {
|
@media screen(navigation) {
|
||||||
|
|
@ -132,10 +193,15 @@
|
||||||
--nav-button-display: none;
|
--nav-button-display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mainnav :is(a, [data-submenu-toggle]) {
|
||||||
|
--nav-item-font-weight: var(--font-regular);
|
||||||
|
}
|
||||||
|
|
||||||
.mainnav ul {
|
.mainnav ul {
|
||||||
--nav-list-layout: row;
|
--cluster-direction: row;
|
||||||
--nav-list-position: static;
|
--nav-list-position: static;
|
||||||
--nav-list-padding: 0;
|
--nav-list-padding-block: 0;
|
||||||
|
--nav-list-padding-inline: 0;
|
||||||
--nav-list-height: auto;
|
--nav-list-height: auto;
|
||||||
--nav-list-width: 100%;
|
--nav-list-width: 100%;
|
||||||
--nav-list-shadow: none;
|
--nav-list-shadow: none;
|
||||||
|
|
@ -145,20 +211,42 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainnav [aria-current='page'],
|
.mainnav [aria-current='page'],
|
||||||
.mainnav [data-state='active'] {
|
.mainnav [data-state='active'],
|
||||||
|
li:has(ul a[aria-current='page']) > [data-submenu-toggle] {
|
||||||
--nav-item-background: transparent;
|
--nav-item-background: transparent;
|
||||||
--nav-item-text-color: var(--color-primary);
|
--nav-item-text-color: var(--color-primary);
|
||||||
--nav-item-decoration-color: var(--color-primary);
|
--nav-item-decoration-color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mainnav [data-submenu-toggle] {
|
||||||
|
inline-size: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav [data-submenu-toggle] svg {
|
||||||
|
margin-inline-end: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainnav .nav-sublist {
|
||||||
|
--nav-sublist-position: absolute;
|
||||||
|
--nav-sublist-background: var(--color-bg);
|
||||||
|
--nav-sublist-border: var(--color-text);
|
||||||
|
--nav-sublist-width: max-content;
|
||||||
|
--nav-list-padding-block: var(--space-xs);
|
||||||
|
--nav-list-padding-inline: var(--space-xs);
|
||||||
|
border: 3px solid var(--nav-sublist-border);
|
||||||
|
inset-block-start: var(--space-xl);
|
||||||
|
inset-inline-start: var(--space-2xs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Repeat the settings to provide a different styling when JavaScript is disabled or drawerNav is set to false. The selector
|
/* Repeat the settings to provide a different styling when JavaScript is disabled or drawerNav is set to false. The selector
|
||||||
assumes that the button doesn’t exist without JS, making the list the first child within the navigation. */
|
assumes that the button doesn’t exist without JS, making the list the first child within the navigation. */
|
||||||
|
|
||||||
.mainnav ul:first-child {
|
.mainnav ul:first-child {
|
||||||
--nav-list-layout: row;
|
--cluster-direction: row;
|
||||||
--nav-list-position: static;
|
--nav-list-position: static;
|
||||||
--nav-list-padding: 0;
|
--nav-list-padding-block: 0;
|
||||||
|
--nav-list-padding-inline: 0;
|
||||||
--nav-list-height: auto;
|
--nav-list-height: auto;
|
||||||
--nav-list-width: 100%;
|
--nav-list-width: 100%;
|
||||||
--nav-list-shadow: none;
|
--nav-list-shadow: none;
|
||||||
|
|
@ -178,3 +266,19 @@ assumes that the button doesn’t exist without JS, making the list the first ch
|
||||||
.mainnav:has(ul:first-child) {
|
.mainnav:has(ul:first-child) {
|
||||||
--nav-position: relative;
|
--nav-position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* no JS fallback for sub menus */
|
||||||
|
@media (scripting: none) {
|
||||||
|
.mainnav ul:first-child ul.nav-sublist {
|
||||||
|
--cluster-direction: row;
|
||||||
|
--cluster-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (scripting: none) {
|
||||||
|
@media screen(navigation) {
|
||||||
|
.mainnav ul:first-child ul.nav-sublist {
|
||||||
|
--cluster-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ Can be any acceptable flexbox alignment value.
|
||||||
|
|
||||||
.cluster {
|
.cluster {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: var(--cluster-direction, row);
|
||||||
|
flex-wrap: var(--cluster-wrap, wrap);
|
||||||
gap: var(--gutter, var(--space-s-l));
|
gap: var(--gutter, var(--space-s-l));
|
||||||
justify-content: var(--cluster-horizontal-alignment, flex-start);
|
justify-content: var(--cluster-horizontal-alignment, flex-start);
|
||||||
align-items: var(--cluster-vertical-alignment, center);
|
align-items: var(--cluster-vertical-alignment, center);
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,30 @@
|
||||||
const nav = document.querySelector('nav');
|
const nav = document.querySelector('nav');
|
||||||
const list = nav.querySelector('ul');
|
const list = nav.querySelector('ul');
|
||||||
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
|
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
|
||||||
const button = burgerClone.querySelector('button');
|
const buttonDrawer = burgerClone.querySelector('button[data-drawer-toggle]');
|
||||||
|
|
||||||
list.style.setProperty('display', 'flex');
|
list.style.setProperty('display', 'flex');
|
||||||
|
|
||||||
button.addEventListener('click', e => {
|
buttonDrawer.addEventListener('click', e => {
|
||||||
const isOpen = button.getAttribute('aria-expanded') === 'true';
|
const isOpenDrawer = buttonDrawer.getAttribute('aria-expanded') === 'true';
|
||||||
button.setAttribute('aria-expanded', !isOpen);
|
buttonDrawer.setAttribute('aria-expanded', !isOpenDrawer);
|
||||||
});
|
});
|
||||||
|
|
||||||
const disableMenu = () => {
|
const disableMenu = () => {
|
||||||
button.setAttribute('aria-expanded', false);
|
buttonDrawer.setAttribute('aria-expanded', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// close on escape
|
// close on escape
|
||||||
nav.addEventListener('keyup', e => {
|
nav.addEventListener('keyup', event => {
|
||||||
if (e.code === 'Escape') {
|
if (event.code === 'Escape') {
|
||||||
disableMenu();
|
disableMenu();
|
||||||
|
buttonDrawer.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// close if clicked outside of event target
|
// close if clicked outside of event target
|
||||||
document.addEventListener('click', e => {
|
document.addEventListener('click', event => {
|
||||||
const isClickInsideElement = nav.contains(e.target);
|
const isClickInsideElement = nav.contains(event.target);
|
||||||
if (!isClickInsideElement) {
|
if (!isClickInsideElement) {
|
||||||
disableMenu();
|
disableMenu();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
src/assets/scripts/bundle/nav-sub.js
Normal file
45
src/assets/scripts/bundle/nav-sub.js
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
const nav = document.querySelector('nav');
|
||||||
|
const navBreakpoint = '{{ designTokens.viewports.navigation }}';
|
||||||
|
|
||||||
|
// toggle submenu and aria-expanded on button click
|
||||||
|
nav.addEventListener('click', event => {
|
||||||
|
const buttonSub = event.target.closest('button[data-submenu-toggle]');
|
||||||
|
if (!buttonSub) return;
|
||||||
|
|
||||||
|
const isOpenSub = buttonSub.getAttribute('aria-expanded') === 'true';
|
||||||
|
|
||||||
|
// if above nav breakpoint, close any other open submenu first
|
||||||
|
if (window.innerWidth >= navBreakpoint && !isOpenSub) {
|
||||||
|
const openButton = nav.querySelector('button[data-submenu-toggle][aria-expanded="true"]');
|
||||||
|
if (openButton && openButton !== buttonSub) {
|
||||||
|
closeSubmenu(openButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonSub.setAttribute('aria-expanded', String(!isOpenSub));
|
||||||
|
const submenu = document.getElementById(buttonSub.getAttribute('aria-controls'));
|
||||||
|
submenu.hidden = isOpenSub;
|
||||||
|
});
|
||||||
|
|
||||||
|
// close on click outside nav
|
||||||
|
document.addEventListener('click', event => {
|
||||||
|
const openButton = nav.querySelector('button[data-submenu-toggle][aria-expanded="true"]');
|
||||||
|
if (openButton && !nav.contains(event.target)) {
|
||||||
|
closeSubmenu(openButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// close on ESC
|
||||||
|
document.addEventListener('keyup', event => {
|
||||||
|
if (event.code !== 'Escape') return;
|
||||||
|
const openButton = nav.querySelector('button[data-submenu-toggle][aria-expanded="true"]');
|
||||||
|
if (openButton) {
|
||||||
|
closeSubmenu(openButton);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function closeSubmenu(buttonSub) {
|
||||||
|
const submenu = document.getElementById(buttonSub.getAttribute('aria-controls'));
|
||||||
|
buttonSub.setAttribute('aria-expanded', 'false');
|
||||||
|
submenu.hidden = true;
|
||||||
|
}
|
||||||
12
src/assets/svg/misc/chev-down.svg
Normal file
12
src/assets/svg/misc/chev-down.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<svg
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="m6 9 6 6 6-6" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 201 B |
|
|
@ -6,7 +6,9 @@ Edit your navigation items in `src/_data/navigation.js`.
|
||||||
|
|
||||||
You have two options for mobile navigation: by default, the navigation on small displays is converted to small pills that wrap. This does not require any additional JavaScript.
|
You have two options for mobile navigation: by default, the navigation on small displays is converted to small pills that wrap. This does not require any additional JavaScript.
|
||||||
|
|
||||||
You can activate a drawer menu in `src/_data/meta.js`:
|
**Drawer Menu**
|
||||||
|
|
||||||
|
You can activate a drawer menu for mobile in `src/_data/meta.js`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
navigation: {
|
navigation: {
|
||||||
|
|
@ -25,4 +27,31 @@ Adjust your menu breakpoint in `src/_data/designTokens/viewports.json`
|
||||||
"navigation": 662,
|
"navigation": 662,
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Submenu**
|
||||||
|
|
||||||
|
You can activate submenus in `src/_data/meta.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
navigation: {
|
||||||
|
// other settings
|
||||||
|
subMenu: true,
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
This includes the JavaScript for the submenu functionality. Add your submenu items to `src/_data/navigation.js` using this structure:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
text: 'Unlinked parent',
|
||||||
|
url: '#',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
text: 'Sub Item',
|
||||||
|
url: '/sub-item/'
|
||||||
|
},
|
||||||
|
... more items
|
||||||
|
]
|
||||||
|
},
|
||||||
```
|
```
|
||||||
Loading…
Reference in a new issue