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:
|
||||
'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.
|
||||
feedLinks: [{title: 'Atom Feed', url: '/feed.xml', type: 'application/atom+xml'}],
|
||||
feedLinks: [
|
||||
{
|
||||
title: 'Atom Feed',
|
||||
url: '/feed.xml',
|
||||
type: 'application/atom+xml'
|
||||
}
|
||||
],
|
||||
// Tags
|
||||
tagSingle: 'Tag',
|
||||
tagPlural: 'Tags',
|
||||
|
|
@ -51,7 +57,8 @@ module.exports = {
|
|||
ariaTop: 'Main',
|
||||
ariaBottom: 'Complementary',
|
||||
ariaPlatforms: 'Platforms',
|
||||
closedText: 'Menu'
|
||||
closedText: 'Menu',
|
||||
drawerMenu: true
|
||||
},
|
||||
themeSwitch: {
|
||||
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