UX improvements
parent
09cefeb12d
commit
eca4da86c3
|
@ -16,11 +16,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<ul>{{ range .Site.Menus.main }}
|
||||
<li><a href="{{ .URL | relURL }}">{{ .Name }}</a></li>{{ end }}
|
||||
</ul>
|
||||
</nav>
|
||||
{{ partial "nav.html" . }}
|
||||
</header>
|
||||
{{ block "main" . }} {{ end }}
|
||||
<hr/>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<script src="/js/clicky-menus.js"></script>
|
||||
<nav id="navigation">
|
||||
<ul class="clicky-menu no-js">
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="https://acefox.life" rel="me">Blog</a></li>
|
||||
<li><a href="#">Projects</a>
|
||||
<ul>
|
||||
<li><a href="/commissions">Art</a></li>
|
||||
<li><a href="/programs">Programs</a></li>
|
||||
<li><a href="/recipe">Recipes</a></li>
|
||||
<li><a href="/translations">Translations</a></li>
|
||||
</ul></li>
|
||||
<li><a href="/system">System Reference</a></li>
|
||||
<li><a href="/links">Links</a></li>
|
||||
</ul>
|
||||
</nav>
|
|
@ -2,6 +2,9 @@ html {
|
|||
font-family: var(--font);
|
||||
}
|
||||
article, hr, footer {
|
||||
max-width: 40em;
|
||||
margin: 0 auto;
|
||||
width: 48em;
|
||||
margin-left: calc(3em / 5);
|
||||
}
|
||||
article p {
|
||||
text-indent: 3em;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
:root {
|
||||
--font: Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
--font-size: 14pt;
|
||||
/* for whatever reason, this is how wide a character is. 1em is wider. */
|
||||
--char-width: calc(3em / 5);
|
||||
|
||||
/* colours */
|
||||
--normal-red: #B00;
|
||||
|
@ -29,10 +31,12 @@
|
|||
--bold: var(--bright-white);
|
||||
--italic: var(--normal-purple);
|
||||
}
|
||||
body {
|
||||
html {
|
||||
background-color: var(--terminal-bg);
|
||||
color: var(--terminal-fg);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
|
@ -63,33 +67,48 @@ a:visited {
|
|||
nav a {
|
||||
text-decoration: none;
|
||||
}
|
||||
nav a:link, nav a:visited, nav {
|
||||
nav button {
|
||||
font-family: var(--font);
|
||||
font-size: var(--font-size);
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
nav a:link, nav a:visited, nav, nav button {
|
||||
color: var(--normal-black);
|
||||
background-color: var(--normal-white);
|
||||
}
|
||||
nav a:hover, nav a:active, nav a:visited:hover {
|
||||
nav a:hover, nav a:active, nav a:visited:hover, nav button:hover {
|
||||
color: var(--bright-white);
|
||||
background-color: var(--normal-black);
|
||||
}
|
||||
nav > ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
nav li {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
article, hr, footer {
|
||||
margin: 0 auto;
|
||||
margin: 0 var(--char-width);
|
||||
padding: 0;
|
||||
margin-top: 2ex;
|
||||
margin-bottom: 2ex;
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
nav li > ul {
|
||||
position: absolute;
|
||||
padding: 12px 0;
|
||||
background-color: var(--normal-white);
|
||||
visibility: hidden;
|
||||
}
|
||||
nav li > ul li {
|
||||
display: block;
|
||||
}
|
||||
nav li:hover.no-js > ul {
|
||||
visibility: visible;
|
||||
}
|
||||
nav li:focus-within.no-js > ul { /* separate from above for older browsers. */
|
||||
visibility: visible;
|
||||
}
|
||||
/* JavaScript menus */
|
||||
nav ul[aria-hidden="false"] {
|
||||
visibility: visible;
|
||||
}
|
||||
article ul {
|
||||
list-style-type: '- ';
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* Object for creating click-triggered navigation submenus
|
||||
*
|
||||
* Thanks for the inspiration:
|
||||
* - https://www.lottejackson.com/learning/a-reusable-javascript-toggle-pattern
|
||||
* - https://codepen.io/lottejackson/pen/yObQRM
|
||||
*
|
||||
* from https://github.com/mrwweb/clicky-menus
|
||||
*/
|
||||
|
||||
( function() {
|
||||
'use strict';
|
||||
|
||||
const ClickyMenus = function( menu ) {
|
||||
// DOM element(s)
|
||||
const container = menu.parentElement;
|
||||
let currentMenuItem,
|
||||
i,
|
||||
len;
|
||||
|
||||
this.init = function() {
|
||||
menuSetup();
|
||||
document.addEventListener( 'click', closeOpenMenu );
|
||||
};
|
||||
|
||||
/*===================================================
|
||||
= Menu Open / Close Functions =
|
||||
===================================================*/
|
||||
function toggleOnMenuClick( e ) {
|
||||
const button = e.currentTarget;
|
||||
|
||||
// close open menu if there is one
|
||||
if ( currentMenuItem && button !== currentMenuItem ) {
|
||||
toggleSubmenu( currentMenuItem );
|
||||
}
|
||||
|
||||
toggleSubmenu( button );
|
||||
}
|
||||
|
||||
function toggleSubmenu( button ) {
|
||||
const submenu = document.getElementById( button.getAttribute( 'aria-controls' ) );
|
||||
|
||||
if ( 'true' === button.getAttribute( 'aria-expanded' ) ) {
|
||||
button.setAttribute( 'aria-expanded', false );
|
||||
submenu.setAttribute( 'aria-hidden', true );
|
||||
currentMenuItem = false;
|
||||
} else {
|
||||
button.setAttribute( 'aria-expanded', true );
|
||||
submenu.setAttribute( 'aria-hidden', false );
|
||||
preventOffScreenSubmenu( submenu );
|
||||
currentMenuItem = button;
|
||||
}
|
||||
}
|
||||
|
||||
function preventOffScreenSubmenu( submenu ) {
|
||||
const screenWidth = window.innerWidth ||
|
||||
document.documentElement.clientWidth ||
|
||||
document.body.clientWidth,
|
||||
parent = submenu.offsetParent,
|
||||
menuLeftEdge = parent.getBoundingClientRect().left,
|
||||
menuRightEdge = menuLeftEdge + submenu.offsetWidth;
|
||||
|
||||
if ( menuRightEdge + 32 > screenWidth ) { // adding 32 so it's not too close
|
||||
submenu.classList.add( 'sub-menu--right' );
|
||||
}
|
||||
}
|
||||
|
||||
function closeOnEscKey( e ) {
|
||||
if ( 27 === e.keyCode ) {
|
||||
// we're in a submenu item
|
||||
if ( null !== e.target.closest( 'ul[aria-hidden="false"]' ) ) {
|
||||
currentMenuItem.focus();
|
||||
toggleSubmenu( currentMenuItem );
|
||||
|
||||
// we're on a parent item
|
||||
} else if ( 'true' === e.target.getAttribute( 'aria-expanded' ) ) {
|
||||
toggleSubmenu( currentMenuItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeOpenMenu( e ) {
|
||||
if ( currentMenuItem && ! e.target.closest( '#' + container.id ) ) {
|
||||
toggleSubmenu( currentMenuItem );
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================
|
||||
= Modify Menu Markup & Bind Listeners =
|
||||
=============================================================*/
|
||||
function menuSetup() {
|
||||
menu.classList.remove( 'no-js' );
|
||||
const submenuSelector = 'clickySubmenuSelector' in menu.dataset ? menu.dataset.clickySubmenuSelector : 'ul';
|
||||
|
||||
menu.querySelectorAll( submenuSelector ).forEach( ( submenu ) => {
|
||||
const menuItem = submenu.parentElement;
|
||||
|
||||
if ( 'undefined' !== typeof submenu ) {
|
||||
const button = convertLinkToButton( menuItem );
|
||||
|
||||
setUpAria( submenu, button );
|
||||
|
||||
// bind event listener to button
|
||||
button.addEventListener( 'click', toggleOnMenuClick );
|
||||
menu.addEventListener( 'keyup', closeOnEscKey );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Why do this? See https://justmarkup.com/articles/2019-01-21-the-link-to-button-enhancement/
|
||||
*
|
||||
* @param {HTMLElement} menuItem An element representing a link to be converted to a button
|
||||
*/
|
||||
function convertLinkToButton( menuItem ) {
|
||||
const link = menuItem.getElementsByTagName( 'a' )[ 0 ],
|
||||
linkHTML = link.innerHTML,
|
||||
linkAtts = link.attributes,
|
||||
button = document.createElement( 'button' );
|
||||
|
||||
if ( null !== link ) {
|
||||
// copy button attributes and content from link
|
||||
button.innerHTML = linkHTML.trim();
|
||||
for ( i = 0, len = linkAtts.length; i < len; i++ ) {
|
||||
const attr = linkAtts[ i ];
|
||||
if ( 'href' !== attr.name ) {
|
||||
button.setAttribute( attr.name, attr.value );
|
||||
}
|
||||
}
|
||||
|
||||
menuItem.replaceChild( button, link );
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
function setUpAria( submenu, button ) {
|
||||
const submenuId = submenu.getAttribute( 'id' );
|
||||
|
||||
let id;
|
||||
if ( null === submenuId ) {
|
||||
id = button.textContent.trim().replace( /\s+/g, '-' ).toLowerCase() + '-submenu';
|
||||
} else {
|
||||
id = submenuId + '-submenu';
|
||||
}
|
||||
|
||||
// set button ARIA
|
||||
button.setAttribute( 'aria-controls', id );
|
||||
button.setAttribute( 'aria-expanded', false );
|
||||
|
||||
// set submenu ARIA
|
||||
submenu.setAttribute( 'id', id );
|
||||
submenu.setAttribute( 'aria-hidden', true );
|
||||
}
|
||||
};
|
||||
|
||||
/* Create a ClickMenus object and initiate menu for any menu with .clicky-menu class */
|
||||
document.addEventListener( 'DOMContentLoaded', function() {
|
||||
const menus = document.querySelectorAll( '.clicky-menu' );
|
||||
|
||||
menus.forEach( ( menu ) => {
|
||||
const clickyMenu = new ClickyMenus( menu );
|
||||
clickyMenu.init();
|
||||
} );
|
||||
} );
|
||||
}() );
|
Loading…
Reference in New Issue