Instantly share code, notes, and snippets.
Last active Dec 22, 2022
Simple, accessible, nav menu system that is keyboard friendly. Demo here: https://codepen.io/marcamos/pen/zYEXegV
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const navButtonEl = '[aria-controls^="nav-menu-"]'; | |
const navMenuEl = '[id^="nav-menu-"]'; | |
const navButtons = Array.from(document.querySelectorAll(navButtonEl)); | |
const navMenus = Array.from(document.querySelectorAll(navMenuEl)); | |
const closeNavMenu = () => { | |
navButtons.forEach(button => { | |
button.setAttribute('aria-expanded', false); | |
}); | |
navMenus.forEach(menu => { | |
menu.hidden = true; | |
}); | |
} | |
navButtons.forEach(button => { | |
button.addEventListener('click', (el) => { | |
const associatedMenu = el.currentTarget.getAttribute('aria-controls'); | |
navButtons.filter(el => el.getAttribute('aria-controls') != associatedMenu).forEach(otherbutton => { | |
otherbutton.setAttribute('aria-expanded', false); | |
}); | |
navMenus.filter(el => el.id != associatedMenu).forEach(otherMenu => { | |
otherMenu.hidden = true; | |
}); | |
const menuExpanded = button.getAttribute('aria-expanded') === 'true' || false; | |
button.setAttribute('aria-expanded', !menuExpanded); | |
const navMenu = document.getElementById(associatedMenu); | |
navMenu.hidden = !navMenu.hidden; | |
}); | |
}); | |
document.addEventListener('click', (el) => { | |
el.target.closest(navButtonEl) || el.target.closest(navMenuEl) ? '' : closeNavMenu(); | |
}); | |
document.addEventListener('keyup', (e) => { | |
e.key === "Escape" ? closeNavMenu() : ''; | |
}); | |
// The above assumes HTML like this: | |
// (note: each button / div pair is usually wrapped in a nav element and unordered list, etc. what you see below is the bare minimum) | |
// | |
// <button aria-controls="nav-menu-one" aria-expanded="false">Button One</button> | |
// <div id="nav-menu-one" hidden> | |
// stuff that is hidden until Button One is clicked | |
// </div> | |
// | |
// <button aria-controls="nav-menu-two" aria-expanded="false">Button Two</button> | |
// <div id="nav-menu-two" hidden> | |
// stuff that is hidden until Button Two is clicked | |
// </div> | |
// | |
// <button aria-controls="nav-menu-three" aria-expanded="false">Button Three</button> | |
// <div id="nav-menu-three" hidden> | |
// stuff that is hidden until Button Three is clicked | |
// </div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment