Refactor navigation hamburger menu to an accordion

This commit is contained in:
Helen Chong 2024-06-12 01:24:10 +08:00
parent 64b49b5048
commit 00baf37c40
1 changed files with 74 additions and 57 deletions

View File

@ -1,21 +1,34 @@
{# Accessible hamburger menu code based on:
https://kalechips.net/projects/snippets/burger #}
{% set navLinksEl %}{% block navbarLinks %}{{ navbarLinks }}{% endblock %}{% endset %}
<nav class="navbar"> <nav class="navbar">
<button class="navbar__toggle" aria-label="Navigation menu toggle" aria-expanded="false"> <details class="navbar__burger">
<span aria-hidden="true">☰</span> <summary class="navbar__toggle" id="toggle">☰ Navigation</summary>
<h2 class="navbar__title">Navigation</h2> <nav class="navbar__menu">
</button> <ul class="navbar__menu--links">
{{ navLinksEl | safe }}
<li class="skip"><a href="#toggle">Close Menu</a></li>
</ul>
</nav>
</details>
<ul class="navbar__links"> <ul class="navbar__links">
{% block navbarLinks %} {{ navLinksEl | safe }}
{{ navbarLinks }}
{% endblock %}
</ul> </ul>
</nav> </nav>
<style> <style>
:root {
--icon-burger: url(/assets/icons/burger.svg);
--icon-close: url(/assets/icons/close.svg);
--sz-icon: 2.5rem;
}
.navbar { .navbar {
background: var(--clr-navbar-bg); background: var(--clr-navbar-bg);
padding: 0.6em 1em;
width: 100%; width: 100%;
z-index: 999; z-index: 998;
position: sticky; position: sticky;
top: 0; top: 0;
} }
@ -24,35 +37,39 @@
.navbar__title { .navbar__title {
color: var(--clr-navbar-link); color: var(--clr-navbar-link);
font-size: 1.3rem; font-size: 1.3rem;
font-weight: 700;
} }
.navbar__toggle { .navbar__toggle {
list-style-type: none;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.3em; gap: 0.3em;
border: none; padding: 0.6em;
padding: 0;
margin: 0;
background-color: inherit; background-color: inherit;
} }
.navbar__toggle::-webkit-details-marker {
display: none;
}
.navbar__toggle:focus, .navbar__toggle:focus,
.navbar__links a:focus { .navbar a:focus {
outline: 0.15em solid var(--clr-navbar-link); outline: 0.15em solid var(--clr-navbar-link);
} }
.navbar a:focus {
outline-offset: 0.1em;
}
.navbar__menu--links,
.navbar__links { .navbar__links {
list-style: none; list-style: none;
padding: 0.2em 0 0 0;
display: none;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1em; gap: 1em;
} }
.navbar__links--show { .navbar__menu--links a,
display: flex;
}
.navbar__links a { .navbar__links a {
color: var(--clr-navbar-link); color: var(--clr-navbar-link);
text-decoration: none; text-decoration: none;
@ -60,6 +77,31 @@
display: block; display: block;
} }
.navbar__menu--links {
display: flex;
padding: 0 1em;
}
.skip a {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.skip a:focus {
position: static;
width: auto;
height: auto;
}
.navbar__links {
display: none;
padding: 0.2em 0 0 0;
}
.navbar__links a:hover { .navbar__links a:hover {
color: var(--clr-link-hover); color: var(--clr-link-hover);
} }
@ -74,6 +116,10 @@
padding: 0 0.6em; padding: 0 0.6em;
} }
.navbar__burger {
display: none;
}
.navbar__toggle { .navbar__toggle {
display: none; display: none;
} }
@ -88,44 +134,15 @@
</style> </style>
<script defer> <script defer>
{# Accessible hamburger menu navigation script based on: window.onload = () => {
https://accessibleweb.dev/navigation #} const navbarBurger = document.querySelector(".navbar__burger");
const navbarToggle = document.querySelector(".navbar__toggle");
const navbarLinksClass = ".navbar__links";
const navbarLinks = document.querySelector(navbarLinksClass);
const showNavLinksClass = "navbar__links--show";
const navbarLinkItems = document.querySelectorAll(navbarLinksClass + " li a");
const openNavigation = () => { navbarBurger.addEventListener("keydown", (event) => {
navbarLinks.classList.add(showNavLinksClass); const key = event.code;
navbarToggle.ariaExpanded = "true"; if (key == "Escape") {
navbarBurger.removeAttribute("open");
document.querySelector(".navbar__toggle").focus();
}
});
}; };
const closeNavigation = () => {
navbarLinks.classList.remove(showNavLinksClass);
navbarToggle.ariaExpanded = "false";
};
const toggleNavigation = () => {
const open = navbarToggle.ariaExpanded;
open === "false" ? openNavigation() : closeNavigation();
}
navbarToggle.addEventListener("click", toggleNavigation);
window.addEventListener("keyup", (e) => {
if (e.key === "Escape") {
navbarToggle.focus();
closeNavigation();
}
});
const handleBlur = (event) => {
const navList = event.currentTarget.closest(navbarLinksClass);
if (!event.relatedTarget || !navList.contains(event.relatedTarget)) {
closeNavigation();
}
};
navbarLinkItems[navbarLinkItems.length - 1].addEventListener("blur", handleBlur);
</script> </script>