Use popover for hamburger navigation menu
This commit is contained in:
parent
6c31a6fa6b
commit
92e06385f7
|
@ -1,6 +1,3 @@
|
||||||
{# Accessible hamburger menu code based on:
|
|
||||||
https://kalechips.net/projects/snippets/burger #}
|
|
||||||
|
|
||||||
{% set navLinksEl %}
|
{% set navLinksEl %}
|
||||||
{%- if tags and tags.includes("shrine pages") %}
|
{%- if tags and tags.includes("shrine pages") %}
|
||||||
<li>
|
<li>
|
||||||
|
@ -15,131 +12,86 @@ https://kalechips.net/projects/snippets/burger #}
|
||||||
{% endset %}
|
{% endset %}
|
||||||
|
|
||||||
<nav class="navbar" aria-labelledby="top-level-nav-title">
|
<nav class="navbar" aria-labelledby="top-level-nav-title">
|
||||||
<h2 class="visually-hidden" id="top-level-nav-title">Top Level Navigation Bar</h2>
|
<h2 class="visually-hidden" id="top-level-nav-title">Top Level</h2>
|
||||||
<details class="navbar__burger">
|
<ul class="navbar__menu navbar__links">{{ navLinksEl | safe }}</ul>
|
||||||
<summary class="navbar__toggle" id="navbar-toggle">
|
<button class="navbar__toggle" popovertarget="nav-menu" aria-labelledby="nav-toggle-title">
|
||||||
<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg aria-hidden="true" focusable="false" width="1em" height="1em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 96C0 78.3 14.3 64 32 64l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32L32 448c-17.7 0-32-14.3-32-32s14.3-32 32-32l384 0c17.7 0 32 14.3 32 32z"/></svg>
|
||||||
<path d="M4 6H20M4 12H20M4 18H20" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
Navigation
|
Navigation
|
||||||
</summary>
|
</button>
|
||||||
<nav class="navbar__menu" aria-labelledby="hamburger-nav-title">
|
|
||||||
<h3 class="visually-hidden" id="hamburger-nav-title">Hamburger Menu</h3>
|
|
||||||
<ul class="navbar__menu--links">
|
|
||||||
{{ navLinksEl | safe }}
|
|
||||||
<li class="skip"><a href="#navbar-toggle">Close Menu</a></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</details>
|
|
||||||
<ul class="navbar__links">
|
|
||||||
{{ navLinksEl | safe }}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
<div popover id="nav-menu" class="navbar__popover">
|
||||||
|
<ul class="navbar__menu">{{ navLinksEl | safe }}</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
{%- css %}
|
{%- css %}
|
||||||
: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);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 998;
|
z-index: 998;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
padding: 0.6em;
|
||||||
|
|
||||||
.navbar__toggle {
|
|
||||||
color: var(--clr-navbar-link);
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar__toggle {
|
|
||||||
list-style-type: none;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.3em;
|
|
||||||
padding: 0.4em 0.6em;
|
|
||||||
background-color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar__toggle::-webkit-details-marker { display: none; }
|
|
||||||
|
|
||||||
.navbar__toggle:focus,
|
|
||||||
.navbar a:focus {
|
|
||||||
outline: 0.15em solid var(--clr-navbar-link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar a:focus { outline-offset: 0.1em; }
|
.navbar a:focus { outline-offset: 0.1em; }
|
||||||
|
|
||||||
.navbar__menu--links,
|
.navbar__toggle {
|
||||||
.navbar__links {
|
background-color: inherit;
|
||||||
list-style-type: "";
|
color: var(--clr-navbar-link);
|
||||||
flex-wrap: wrap;
|
border: none;
|
||||||
gap: 1em;
|
padding: 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar__menu--links a,
|
.navbar__toggle svg { fill: currentColor; }
|
||||||
.navbar__links a {
|
.navbar__toggle:focus,
|
||||||
|
.navbar a:focus { outline: 0.15em solid var(--clr-navbar-link); }
|
||||||
|
|
||||||
|
.navbar__menu {
|
||||||
|
list-style-type: "";
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar__menu a {
|
||||||
color: var(--clr-navbar-link);
|
color: var(--clr-navbar-link);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar__menu--links {
|
.navbar__menu a:hover { color: var(--clr-link-hover); }
|
||||||
display: flex;
|
.navbar__menu a:focus { outline-offset: 0.2em; }
|
||||||
padding: 0 1em;
|
.navbar__links { display: none; }
|
||||||
|
|
||||||
|
.navbar__popover {
|
||||||
|
background-color: var(--clr-navbar-bg);
|
||||||
|
border: 0.15em solid var(--clr-navbar-link);
|
||||||
|
padding: 1.5em;
|
||||||
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skip a {
|
.navbar__popover::backdrop {
|
||||||
position: absolute;
|
background-color: black;
|
||||||
left: -10000px;
|
opacity: 0.5;
|
||||||
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 { color: var(--clr-link-hover); }
|
|
||||||
.navbar__links a:focus { outline-offset: 0.2em; }
|
|
||||||
|
|
||||||
/* Tablet screen size */
|
/* Tablet screen size */
|
||||||
@media only screen and (min-width: 43.75rem) {
|
@media only screen and (min-width: 43.75rem) {
|
||||||
.navbar { padding: 0 0.6em; }
|
.navbar { padding: 1em 0.6em; }
|
||||||
.navbar__burger { display: none; }
|
|
||||||
.navbar__toggle { display: none; }
|
.navbar__toggle { display: none; }
|
||||||
|
|
||||||
.navbar__links {
|
.navbar__links {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% endcss %}
|
{% endcss %}
|
||||||
|
|
||||||
{%- js %}
|
|
||||||
const navbarBurger = document.querySelector(".navbar__burger");
|
|
||||||
navbarBurger.addEventListener("keydown", (event) => {
|
|
||||||
if (event.key == "Escape") {
|
|
||||||
navbarBurger.removeAttribute("open");
|
|
||||||
navbarBurger.ariaExpanded = false;
|
|
||||||
document.querySelector(".navbar__toggle").focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
{% endjs %}
|
|
|
@ -81,8 +81,6 @@ blockquote > * + :not([class]),
|
||||||
.c-blockquote__attribution { margin-top: var(--sz-paragraph-margin); }
|
.c-blockquote__attribution { margin-top: var(--sz-paragraph-margin); }
|
||||||
|
|
||||||
button:hover { cursor: pointer; }
|
button:hover { cursor: pointer; }
|
||||||
|
|
||||||
button:focus,
|
|
||||||
details:focus { outline-offset: 0.2em; }
|
details:focus { outline-offset: 0.2em; }
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: Colophon
|
title: Colophon
|
||||||
keyword: colophon page
|
keyword: colophon page
|
||||||
updated: 2024-07-18
|
updated: 2024-07-20
|
||||||
toc: true
|
toc: true
|
||||||
eleventyNavigation:
|
eleventyNavigation:
|
||||||
order: 14
|
order: 14
|
||||||
|
@ -54,7 +54,6 @@ Due to this website being a static site, JavaScript is used to create dynamic an
|
||||||
* [{% cite "Star Wars: Knights of the Old Republic" %}](/shrines/starwarskotor)
|
* [{% cite "Star Wars: Knights of the Old Republic" %}](/shrines/starwarskotor)
|
||||||
* [{% cite "Cassette Beasts" %}](/shrines/cassettebeasts)
|
* [{% cite "Cassette Beasts" %}](/shrines/cassettebeasts)
|
||||||
* Birthdays of characters from {% cite "A Summer’s End — Hong Kong 1986" %} on its shrine.
|
* Birthdays of characters from {% cite "A Summer’s End — Hong Kong 1986" %} on its shrine.
|
||||||
* When this site is viewed on mobile devices, the navigation bar's hamburger menu uses JavaScript to enable using the Escape key to close the navigation manu.
|
|
||||||
* Scott O'Hara's [ARIA Tooltips](https://github.com/scottaohara/a11y_tooltips) script is used to implement accessible tooltips that meet Web Content Accessibility Guidelines (WCAG) 2.2 success criterion for [1.4.13: Content on Hover or Focus (Level AA)](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html), by allowing visitors to see tooltips on keyboard focus and dismiss tooltips by pressing the Escape key.
|
* Scott O'Hara's [ARIA Tooltips](https://github.com/scottaohara/a11y_tooltips) script is used to implement accessible tooltips that meet Web Content Accessibility Guidelines (WCAG) 2.2 success criterion for [1.4.13: Content on Hover or Focus (Level AA)](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html), by allowing visitors to see tooltips on keyboard focus and dismiss tooltips by pressing the Escape key.
|
||||||
* Zach Leatherman's [details-utils](https://www.npmjs.com/package/@zachleat/details-utils) JavaScript package is used to automatically expand sidebar table of contents on wide screens.
|
* Zach Leatherman's [details-utils](https://www.npmjs.com/package/@zachleat/details-utils) JavaScript package is used to automatically expand sidebar table of contents on wide screens.
|
||||||
* [status.cafe](https://status.cafe/) widget, which is placed on the home page, uses JavaScript to fetch data of my latest status update.
|
* [status.cafe](https://status.cafe/) widget, which is placed on the home page, uses JavaScript to fetch data of my latest status update.
|
||||||
|
|
Loading…
Reference in New Issue