prepare for optional menu drawer
This commit is contained in:
parent
623cf96ff9
commit
efaec51f23
4 changed files with 176 additions and 2 deletions
|
|
@ -30,7 +30,13 @@ module.exports = {
|
||||||
description:
|
description:
|
||||||
'Tell the word what you are writing about in your blog. It will show up on feed readers.',
|
'Tell the word what you are writing about in your blog. It will show up on feed readers.',
|
||||||
// feed links are looped over in the head. You may add more to the array.
|
// feed links are looped over in the head. You may add more to the array.
|
||||||
feedLinks: [{title: 'Atom Feed', url: '/feed.xml', type: 'application/atom+xml'}],
|
feedLinks: [
|
||||||
|
{
|
||||||
|
title: 'Atom Feed',
|
||||||
|
url: '/feed.xml',
|
||||||
|
type: 'application/atom+xml'
|
||||||
|
}
|
||||||
|
],
|
||||||
// Tags
|
// Tags
|
||||||
tagSingle: 'Tag',
|
tagSingle: 'Tag',
|
||||||
tagPlural: 'Tags',
|
tagPlural: 'Tags',
|
||||||
|
|
@ -51,7 +57,8 @@ module.exports = {
|
||||||
ariaTop: 'Main',
|
ariaTop: 'Main',
|
||||||
ariaBottom: 'Complementary',
|
ariaBottom: 'Complementary',
|
||||||
ariaPlatforms: 'Platforms',
|
ariaPlatforms: 'Platforms',
|
||||||
closedText: 'Menu'
|
closedText: 'Menu',
|
||||||
|
drawerMenu: true
|
||||||
},
|
},
|
||||||
themeSwitch: {
|
themeSwitch: {
|
||||||
title: 'Theme',
|
title: 'Theme',
|
||||||
|
|
|
||||||
16
src/_includes/components/burger-template.njk
Normal file
16
src/_includes/components/burger-template.njk
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!-- template element holding a button that needs to be injected when JavaScript is finally available. -->
|
||||||
|
<!-- based on an article by Manuel Matuzovic, https://web.dev/website-navigation/ -->
|
||||||
|
<!-- see also: https://kittygiraudel.com/2022/09/30/templating-in-html/ -->
|
||||||
|
|
||||||
|
<template id="burger-template">
|
||||||
|
<button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
|
||||||
|
<span>Menu</span>
|
||||||
|
<svg width="24" height="24" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M12 3.75a.75.75 0 01.75.75v6.75h6.75a.75.75 0 010 1.5h-6.75v6.75a.75.75 0 01-1.5 0v-6.75H4.5a.75.75 0 010-1.5h6.75V4.5a.75.75 0 01.75-.75z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
117
src/assets/css/blocks/site-nav-drawer.css
Normal file
117
src/assets/css/blocks/site-nav-drawer.css
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
@media (min-width: 38em) {
|
||||||
|
nav.navbar {
|
||||||
|
--nav-button-display: none;
|
||||||
|
--nav-position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar ul {
|
||||||
|
--nav-list-background: transparent;
|
||||||
|
--nav-list-layout: row;
|
||||||
|
--nav-list-position: static;
|
||||||
|
--nav-list-padding: 0;
|
||||||
|
--nav-list-height: auto;
|
||||||
|
--nav-list-width: 100%;
|
||||||
|
--nav-list-shadow: none;
|
||||||
|
--nav-list-transform: none;
|
||||||
|
--nav-list-visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set on parent div to get the right z-index context */
|
||||||
|
.ontop {
|
||||||
|
z-index: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar {
|
||||||
|
position: var(--nav-position, absolute);
|
||||||
|
/* inset-block-start: 0.5rem; */
|
||||||
|
inset-inline-end: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove default list styling and create layout for list */
|
||||||
|
nav.navbar ul {
|
||||||
|
background: var(--nav-list-background, var(--color-light));
|
||||||
|
box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
|
||||||
|
display: flex;
|
||||||
|
flex-direction: var(--nav-list-layout, column);
|
||||||
|
gap: var(--space-s);
|
||||||
|
block-size: var(--nav-list-height, 100vh);
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: var(--nav-list-padding, var(--space-l) var(--space-s));
|
||||||
|
position: var(--nav-list-position, fixed);
|
||||||
|
inset-block-start: 0; /* Logical property. Equivalent to top: 0; */
|
||||||
|
inset-inline-end: 0; /* Logical property. Equivalent to right: 0; */
|
||||||
|
inline-size: var(--nav-list-width, min(22rem, 100vw));
|
||||||
|
visibility: var(--nav-list-visibility, visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar [aria-expanded='false'] + ul {
|
||||||
|
transform: var(--nav-list-transform, translateX(100%));
|
||||||
|
visibility: var(--nav-list-visibility, hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* animates ul only when opening to avoid flash on page load, svg always */
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
nav.navbar [aria-expanded='true'] + ul,
|
||||||
|
nav.navbar svg {
|
||||||
|
transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55),
|
||||||
|
visibility 0.05s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Basic link styling */
|
||||||
|
nav.navbar a {
|
||||||
|
--text-color: var(--color-dark);
|
||||||
|
color: var(--text-color);
|
||||||
|
padding: 0.1rem;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
text-decoration-color: var(--border-color, transparent);
|
||||||
|
text-decoration-thickness: 3px;
|
||||||
|
text-underline-offset: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change the border-color on :hover and :focus */
|
||||||
|
nav.navbar a:where(:hover, :focus) {
|
||||||
|
--border-color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change border-color and color for the active page */
|
||||||
|
nav.navbar [aria-current='page'] {
|
||||||
|
--border-color: var(--color-primary);
|
||||||
|
--text-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset button styling */
|
||||||
|
nav.navbar button {
|
||||||
|
all: unset;
|
||||||
|
display: var(--nav-button-display, flex);
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--space-xs) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar span {
|
||||||
|
font-size: var(--size-step-min-1);
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding-inline-end: var(--space-2xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar svg {
|
||||||
|
block-size: 100%;
|
||||||
|
inline-size: auto;
|
||||||
|
}
|
||||||
|
header svg {
|
||||||
|
transform: translateY(-0.1em);
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.navbar [aria-expanded='true'] svg {
|
||||||
|
transform: var(--nav-list-rotate, rotate(45deg));
|
||||||
|
}
|
||||||
34
src/assets/scripts/menu-drawer.js
Normal file
34
src/assets/scripts/menu-drawer.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
// © Manuel Matuzović: https://web.dev/website-navigation/
|
||||||
|
|
||||||
|
const nav = document.querySelector('nav');
|
||||||
|
const list = nav.querySelector('ul');
|
||||||
|
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
|
||||||
|
const svg = nav.querySelector('svg');
|
||||||
|
|
||||||
|
const button = burgerClone.querySelector('button');
|
||||||
|
button.addEventListener('click', e => {
|
||||||
|
const isOpen = button.getAttribute('aria-expanded') === 'true';
|
||||||
|
button.setAttribute('aria-expanded', !isOpen);
|
||||||
|
});
|
||||||
|
|
||||||
|
// avoid DRY: disabling menu
|
||||||
|
const disableMenu = () => {
|
||||||
|
button.setAttribute('aria-expanded', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// close on escape
|
||||||
|
nav.addEventListener('keyup', e => {
|
||||||
|
if (e.code === 'Escape') {
|
||||||
|
disableMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// close if clicked outside of event target
|
||||||
|
document.addEventListener('click', e => {
|
||||||
|
const isClickInsideElement = nav.contains(e.target);
|
||||||
|
if (!isClickInsideElement) {
|
||||||
|
disableMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
nav.insertBefore(burgerClone, list);
|
||||||
Loading…
Reference in a new issue