WCAG Responsive Accessible Menu Dropdown Library
What is WCAG Responsive Accessible Menu?
Here we have a javascript library with css and html that produces a responsive and mobile compatible dropdown navigation system. When the screen size goes into a mobile width the menu switches to handle bars and then stilll works as a dropdown menuing system.
Also it has toggle arrows showing which menu item is the active one.
Preview
a preview of WCAG Responsive Accessible Menu
What can i use this for?
This is a stand alone script that does not rely on any other libraries, and can be used as your main site menu system.
A JavaScript library to help you generate WCAG accessible menus in the DOM.
The supported menu types are:
Browser Support
Chrome |
Firefox |
Safari |
Edge |
Chromium |
Webkit |
---|---|---|---|---|---|
last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
Found something that doesn't work the way it should in one of the listed browsers above? Open an issue!
Installation
NPM
NPM is recommended for large-scale development, since it works well with bundlers like Webpack or Rollup.
# latest stable
npm install accessible-menu
CDN
For learning/prototyping purposes you can use the latest version with:
<script src="https://cdn.jsdelivr.net/npm/accessible-menu/dist/accessible-menu.js"></script>
For production environments, it is recommend to use a specific version to avoid unforseen breaking changes:
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@3.0.4/dist/accessible-menu.min.js"></script>
Usage
To use accessible-menu, you first need to make sure your menu matches the following structure:
<ul id="example-menu">
<li><a href="/about">About</a></li>
<li class="dropdown">
<a href="#">Projects ▼</a>
<ul>
<li><a href="/projects/awesome">Awesome project</a></li>
<li><a href="/projects/not-so-awesome">Not-so-awesome project</a></li>
</ul>
</li>
<li><a href="/contact">Contact me</a></li>
</ul>
Include accessible-menu through import or bundled library in your project:
import AccessibleMenu from "accessible-menu";
or
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@3.0.4/dist/accessible-menu.min.js"></script>
Once you have accessible-menu loaded, declare a new menu object.
menuElement
is required for all menus, while submenuItemSelector
is only required if you have submenus/dropdowns.
const menu = new AccessibleMenu.DisclosureMenu({
menuElement: document.querySelector("#example-menu"),
submenuItemSelector: "li.dropdown",
});
Only need one type of menu class?
Bundled versions of each menu are provided in the dist and individual exports are provided in the index.
There are also compiled ES Module versions if you don't want to use an iife!
DisclosureMenu usage
import { DisclosureMenu } from "accessible-menu";
or
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@3.0.4/dist/disclosure-menu.min.js"></script>
then
const menu = new DisclosureMenu({
menuElement: document.querySelector("#example-menu"),
submenuItemSelector: "li.dropdown",
});
Menubar usage
import { Menubar } from "accessible-menu";
or
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@3.0.4/dist/menubar.min.js"></script>
then
const menu = new Menubar({
menuElement: document.querySelector("#example-menu"),
submenuItemSelector: "li.dropdown",
});
Treeview usage
import { Treeview } from "accessible-menu";
or
<script src="https://cdn.jsdelivr.net/npm/accessible-menu@3.0.4/dist/treeview.min.js"></script>
then
const menu = new Treeview({
menuElement: document.querySelector("#example-menu"),
submenuItemSelector: "li.dropdown",
});
Documentation
Examples
Looking for a working example of accessible-menu? Check out these jsfiddles:
Bootstrap support
Looking to use this with Bootstrap? Because Bootstrap adds classes to the menu's containing element to show/hide the menu, you'll need custom open/close functions for your menu. Check out the accessible-menu-bootstrap-4 project where all that is done for you!
Original Source
Thanks to the author NickDJM on github.
WCAG Responsive Accessible Menu Dropdown Library Demo
View Demo Full Screen View Demo New Tab
WCAG Responsive Accessible Menu Dropdown Library Code
HTML
<header>
<nav>
<button id="toggle-0" aria-label="Toggle main menu">☰</button>
<ul id="menu-0">
<li id="item-1-0-0"><a id="link-1-0-0" href="#">First item</a></li>
<li id="item-2-0-0" class="dropdown">
<a id="link-2-0-0" href="#">Second item</a>
<ul id="menu-2">
<li id="item-2-1-0"><a id="link-2-1-0" href="#">First item</a></li>
<li id="item-2-2-0" class="dropdown">
<a id="link-2-2-0" href="#">Second item</a>
<ul id="menu-2-2">
<li id="item-2-2-1"><a id="link-2-2-1" href="#">First item</a></li>
<li id="item-2-2-2"><a id="link-2-2-2" href="#">Second item</a></li>
<li id="item-2-2-3"><a id="link-2-2-3" href="#">Third item</a></li>
</ul>
</li>
<li id="item-2-3-0" class="dropdown">
<a id="link-2-3-0" href="#">Third item</a>
<ul id="menu-2-3">
<li id="item-2-3-1"><a id="link-2-3-1" href="#">First item</a></li>
<li id="item-2-3-2"><a id="link-2-3-2" href="#">Second item</a></li>
<li id="item-2-3-3"><a id="link-2-3-3" href="#">Third item</a></li>
</ul>
</li>
</ul>
</li>
<li id="item-3-0-0" class="dropdown">
<a id="link-3-0-0" href="#">Third item</a>
<ul id="menu-3">
<li id="item-3-1-0"><a id="link-3-1-0" href="#">First item</a></li>
<li id="item-3-2-0"><a id="link-3-2-0" href="#">Second item</a></li>
<li id="item-3-3-0"><a id="link-3-3-0" href="#">Third item</a></li>
</ul>
</li>
<li id="item-4-0-0"><a id="link-4-0-0" href="#">Fourth item</a></li>
<li id="item-5-0-0" class="dropdown">
<a id="link-5-0-0" href="#">Fifth item</a>
<ul id="menu-5">
<li id="item-5-1-0"><a id="link-5-1-0" href="#">First item</a></li>
<li id="item-5-2-0"><a id="link-5-2-0" href="#">Second item</a></li>
<li id="item-5-3-0"><a id="link-5-3-0" href="#">Third item</a></li>
</ul>
</li>
</ul>
</nav>
</header>
CSS
* {
box-sizing: border-box; margin: 0; padding: 0;
font-family:"Roboto", sans-serif;
}
*:focus {
outline: 2px dotted #000;
outline-offset: -2px;
box-shadow: 0 0 2px 0 inset #fff; }
*:focus:not(:focus-visible) {
outline: none;
box-shadow: none; }
.lead { font-size: 24px; font-weight: 300; }
body {
display: flex;
flex-direction: column;
min-height: 100vh;
font-family: 'Inter'; }
main {
padding: 1rem 6rem; }
nav {
background-color: #293345;
color: #3bc993; }
nav > button {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
border: 0;
background-color: #293345;
color: #3bc993;
font-size: 2.5rem; }
nav ul {
display: none;
margin: 0;
padding: 0;
background-color: #293345;
color: #3bc993;
list-style: none; }
nav ul.show {
display: grid;
grid-auto-flow: row;
grid-auto-rows: max-content; }
nav a {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
padding: 0.75rem 1.5rem;
transition: background-color 150ms ease-in-out;
color: #3bc993;
text-decoration: none; }
nav a:hover {
background-color: #3bc993;
color: #293345; }
nav li {
padding: 0.25rem; }
nav li.dropdown {
position: relative; }
nav li.dropdown > a::after {
content: "▼";
display: block;
margin-left: 0.5rem;
transition: transform 250ms linear;
font-size: 0.5em; }
nav li.dropdown > a[aria-expanded="true"]::after {
transform: rotate(-180deg); }
nav li.dropdown ul a {
padding-left: 2.25rem; }
nav li.dropdown ul li.dropdown ul a {
padding-left: 3.375rem; }
@media screen and (min-width: 1080px) {
nav button {
display: none; }
nav > ul,
nav > ul.show {
display: grid;
grid-auto-columns: max-content;
grid-auto-flow: column; }
nav .dropdown ul.show {
position: absolute; }
nav .dropdown ul ul {
top: 0;
left: 100%; } }
Javascript
var DisclosureMenu=function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function o(e,t,o){return t&&n(e.prototype,t),o&&n(e,o),e}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&i(e,t)}function l(e){return(l=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function i(e,t){return(i=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function u(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function c(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?u(e):t}function a(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,o=l(e);if(t){var s=l(this).constructor;n=Reflect.construct(o,arguments,s)}else n=o.apply(this,arguments);return c(this,n)}}function m(e,t,n){return(m="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,n){var o=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=l(e)););return e}(e,t);if(o){var s=Object.getOwnPropertyDescriptor(o,t);return s.get?s.get.call(n):s.value}})(e,t,n||e)}function h(e){return function(e){if(Array.isArray(e))return f(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return f(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return f(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n<t;n++)o[n]=e[n];return o}function d(t,n){try{if("object"!==e(n)){var o=e(n);throw new TypeError("AccessibleMenu: Elements given to isValidInstance() must be inside of an object. ".concat(o," given."))}for(var s in n)if(!(n[s]instanceof t)){var r=e(n[s]);throw new TypeError("AccessibleMenu: ".concat(s," must be an instance of ").concat(t.name,". ").concat(r," given."))}return!0}catch(e){return console.error(e),!1}}function p(t,n){try{if("object"!==e(n)){var o=e(n);throw new TypeError("AccessibleMenu: Values given to isValidType() must be inside of an object. ".concat(o," given."))}for(var s in n){var r=e(n[s]);if(r!==t)throw new TypeError("AccessibleMenu: ".concat(s," must be a ").concat(t,". ").concat(r," given."))}return!0}catch(e){return console.error(e),!1}}function v(t){try{if("object"!==e(t)){var n=e(t);throw new TypeError("AccessibleMenu: Values given to isCSSSelector() must be inside of an object. ".concat(n," given."))}for(var o in t)try{if(null===t[o])throw new Error;document.querySelector(t[o])}catch(e){throw new TypeError("AccessibleMenu: ".concat(o,' must be a valid CSS selector. "').concat(t[o],'" given.'))}return!0}catch(e){return console.error(e),!1}}function y(t){try{if("object"!==e(t)||Array.isArray(t)){var n=e(t);throw new TypeError("AccessibleMenu: Values given to isValidClassList() must be inside of an object. ".concat(n," given."))}var o=function(n){var o=e(t[n]);if("string"!==o){if(!Array.isArray(t[n]))throw new TypeError("AccessibleMenu: ".concat(n," must be a string or an array of strings. ").concat(o," given."));t[n].forEach((function(e){if("string"!=typeof e)throw new TypeError("AccessibleMenu: ".concat(n," must be a string or an array of strings. An array containing non-strings given."))}))}else{var s={};s[n]=t[n],v(s)}};for(var s in t)o(s);return!0}catch(e){return console.error(e),!1}}function g(t){try{if("object"!==e(t)){var n=e(t);throw new TypeError("AccessibleMenu: Values given to isValidHoverType() must be inside of an object. ".concat(n," given."))}var o=["off","on","dynamic"];for(var s in t)if(!o.includes(t[s]))throw new TypeError("AccessibleMenu: ".concat(s," must be one of the following values: ").concat(o.join(", "),'. "').concat(t[s],'" given.'));return!0}catch(e){return console.error(e),!1}}function b(e,t){return!(!p("string",{event:e})||!d(HTMLElement,{element:t}))&&void 0!==t["on".concat(e)]}var _=function(){function e(n){var o=n.menuToggleElement,r=n.parentElement,l=n.controlledMenu,i=n.parentMenu,u=void 0===i?null:i;t(this,e),s(this,"_dom",{toggle:null,parent:null}),s(this,"_elements",{controlledMenu:null,parentMenu:null}),s(this,"_open",!1),s(this,"_expandEvent",new CustomEvent("accessibleMenuExpand",{bubbles:!0,detail:{toggle:this}})),s(this,"_collapseEvent",new CustomEvent("accessibleMenuCollapse",{bubbles:!0,detail:{toggle:this}})),this._dom.toggle=o,this._dom.parent=r,this._elements.controlledMenu=l,this._elements.parentMenu=u}return o(e,[{key:"initialize",value:function(){if(this.dom.toggle.setAttribute("aria-haspopup","true"),this.dom.toggle.setAttribute("aria-expanded","false"),function(e,t){if(p("string",{tagName:e})&&d(HTMLElement,t)){var n=e.toLowerCase(),o=!0;for(var s in t)t[s].tagName.toLowerCase()!==n&&(o=!1);return o}return!1}("button",{toggle:this.dom.toggle})||this.dom.toggle.setAttribute("role","button"),""===this.dom.toggle.id||""===this.elements.controlledMenu.dom.menu.id){var e=Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,10),t=this.dom.toggle.innerText.replace(/[^a-zA-Z0-9\s]/g,""),n=e;!t.replace(/\s/g,"").length&&this.dom.toggle.getAttribute("aria-label")&&(t=this.dom.toggle.getAttribute("aria-label").replace(/[^a-zA-Z0-9\s]/g,"")),t.replace(/\s/g,"").length>0&&((t=t.toLowerCase().replace(/\s+/g,"-")).startsWith("-")&&(t=t.substring(1)),t.endsWith("-")&&(t=t.slice(0,-1)),n="".concat(t,"-").concat(n)),this.dom.toggle.id=this.dom.toggle.id||"".concat(n,"-menu-button"),this.elements.controlledMenu.dom.menu.id=this.elements.controlledMenu.dom.menu.id||"".concat(n,"-menu")}this.elements.controlledMenu.dom.menu.setAttribute("aria-labelledby",this.dom.toggle.id),this.dom.toggle.setAttribute("aria-controls",this.elements.controlledMenu.dom.menu.id),this._collapse(!1)}},{key:"dom",get:function(){return this._dom}},{key:"elements",get:function(){return this._elements}},{key:"isOpen",get:function(){return this._open},set:function(e){p("boolean",{value:e}),this._open=e}},{key:"_expand",value:function(){var e,t,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],o=this.elements.controlledMenu,s=o.closeClass,r=o.openClass;(this.dom.toggle.setAttribute("aria-expanded","true"),""!==r)&&("string"==typeof r?this.elements.controlledMenu.dom.menu.classList.add(r):(e=this.elements.controlledMenu.dom.menu.classList).add.apply(e,h(r)));""!==s&&("string"==typeof s?this.elements.controlledMenu.dom.menu.classList.remove(s):(t=this.elements.controlledMenu.dom.menu.classList).remove.apply(t,h(s)));n&&this.dom.toggle.dispatchEvent(this._expandEvent)}},{key:"_collapse",value:function(){var e,t,n=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],o=this.elements.controlledMenu,s=o.closeClass,r=o.openClass;(this.dom.toggle.setAttribute("aria-expanded","false"),""!==s)&&("string"==typeof s?this.elements.controlledMenu.dom.menu.classList.add(s):(e=this.elements.controlledMenu.dom.menu.classList).add.apply(e,h(s)));""!==r&&("string"==typeof r?this.elements.controlledMenu.dom.menu.classList.remove(r):(t=this.elements.controlledMenu.dom.menu.classList).remove.apply(t,h(r)));n&&this.dom.toggle.dispatchEvent(this._collapseEvent)}},{key:"open",value:function(){this.elements.controlledMenu.focusState="self",this._expand(),this.isOpen=!0}},{key:"preview",value:function(){this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this._expand(),this.isOpen=!0}},{key:"close",value:function(){this.isOpen&&(this.elements.controlledMenu.currentChild=0,this.elements.controlledMenu.blur(),this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this._collapse(),this.isOpen=!1)}},{key:"toggle",value:function(){this.isOpen?this.close():this.open()}},{key:"closeSiblings",value:function(){var e=this;this.elements.parentMenu&&this.elements.parentMenu.elements.submenuToggles.forEach((function(t){t!==e&&t.close()}))}},{key:"closeChildren",value:function(){this.elements.controlledMenu.elements.submenuToggles.forEach((function(e){return e.close()}))}}]),e}(),M=function(){function e(n){var o=n.menuItemElement,r=n.menuLinkElement,l=n.parentMenu,i=n.isSubmenuItem,u=void 0!==i&&i,c=n.childMenu,a=void 0===c?null:c,m=n.toggle,h=void 0===m?null:m;t(this,e),s(this,"_dom",{item:null,link:null}),s(this,"_elements",{parentMenu:null,childMenu:null,toggle:null}),s(this,"_submenu",!1),this._dom.item=o,this._dom.link=r,this._elements.parentMenu=l,this._elements.childMenu=a,this._elements.toggle=h,this._submenu=u}return o(e,[{key:"initialize",value:function(){}},{key:"dom",get:function(){return this._dom}},{key:"elements",get:function(){return this._elements}},{key:"isSubmenuItem",get:function(){return this._submenu}},{key:"focus",value:function(){this.elements.parentMenu.shouldFocus&&this.dom.link.focus()}},{key:"blur",value:function(){this.elements.parentMenu.shouldFocus&&this.dom.link.blur()}}]),e}();function E(e){try{var t=e.key||e.keyCode,n={Enter:"Enter"===t||13===t,Space:" "===t||"Spacebar"===t||32===t,Escape:"Escape"===t||"Esc"===t||27===t,ArrowUp:"ArrowUp"===t||"Up"===t||38===t,ArrowRight:"ArrowRight"===t||"Right"===t||39===t,ArrowDown:"ArrowDown"===t||"Down"===t||40===t,ArrowLeft:"ArrowLeft"===t||"Left"===t||37===t,Home:"Home"===t||36===t,End:"End"===t||35===t,Character:isNaN(t)&&!!t.match(/^[a-zA-Z]{1}$/),Tab:"Tab"===t||9===t,Asterisk:"*"===t||56===t};return Object.keys(n).find((function(e){return!0===n[e]}))||""}catch(e){return""}}function C(e){e.preventDefault(),e.stopPropagation()}var T=function(){function n(e){var o=e.menuElement,r=e.menuItemSelector,l=void 0===r?"li":r,i=e.menuLinkSelector,u=void 0===i?"a":i,c=e.submenuItemSelector,a=void 0===c?"":c,m=e.submenuToggleSelector,h=void 0===m?"a":m,f=e.submenuSelector,d=void 0===f?"ul":f,p=e.controllerElement,v=void 0===p?null:p,y=e.containerElement,g=void 0===y?null:y,b=e.openClass,E=void 0===b?"show":b,C=e.closeClass,T=void 0===C?"hide":C,k=e.isTopLevel,w=void 0===k||k,S=e.parentMenu,I=void 0===S?null:S,L=e.hoverType,A=void 0===L?"off":L,O=e.hoverDelay,D=void 0===O?250:O;t(this,n),s(this,"_MenuType",n),s(this,"_MenuItemType",M),s(this,"_MenuToggleType",_),s(this,"_dom",{menu:null,menuItems:[],submenuItems:[],submenuToggles:[],submenus:[],controller:null,container:null}),s(this,"_selectors",{menuItems:"",menuLinks:"",submenuItems:"",submenuToggles:"",submenus:""}),s(this,"_elements",{menuItems:[],submenuToggles:[],controller:null,parentMenu:null,rootMenu:null}),s(this,"_openClass","show"),s(this,"_closeClass","hide"),s(this,"_root",!0),s(this,"_currentChild",0),s(this,"_focusState","none"),s(this,"_currentEvent","none"),s(this,"_hoverType","off"),s(this,"_hoverDelay",250),this._dom.menu=o,this._dom.controller=v,this._dom.container=g,this._selectors.menuItems=l,this._selectors.menuLinks=u,this._selectors.submenuItems=a,this._selectors.submenuToggles=h,this._selectors.submenus=d,this._elements.menuItems=[],this._elements.submenuToggles=[],this._elements.controller=null,this._elements.parentMenu=I,this._elements.rootMenu=w?this:null,this._openClass=E||"",this._closeClass=T||"",this._root=w,this._hoverType=A,this._hoverDelay=D}return o(n,[{key:"initialize",value:function(){if(!this._validate())throw new Error("AccesibleMenu: cannot initialize menu. See other error messages for more information.");if(null===this.elements.rootMenu&&this._findRootMenu(this),this._setDOMElements(),this.isTopLevel&&this.dom.controller&&this.dom.container){var e=new this._MenuToggleType({menuToggleElement:this.dom.controller,parentElement:this.dom.container,controlledMenu:this});this._elements.controller=e}this._createChildElements()}},{key:"dom",get:function(){return this._dom}},{key:"selectors",get:function(){return this._selectors}},{key:"elements",get:function(){return this._elements}},{key:"isTopLevel",get:function(){return this._root}},{key:"openClass",get:function(){return this.isTopLevel?this._openClass:this.elements.rootMenu.openClass},set:function(e){y({openClass:e}),this._openClass!==e&&(this._openClass=e)}},{key:"closeClass",get:function(){return this.isTopLevel?this._closeClass:this.elements.rootMenu.closeClass},set:function(e){y({closeClass:e}),this._closeClass!==e&&(this._closeClass=e)}},{key:"currentChild",get:function(){return this._currentChild},set:function(e){function t(e){if(["mouse","character"].includes(e.currentEvent)&&e.elements.parentMenu)for(var t=0,n=!1;!n&&t<e.elements.parentMenu.elements.menuItems.length;){var o=e.elements.parentMenu.elements.menuItems[t];o.isSubmenuItem&&o.elements.toggle.elements.controlledMenu===e&&(n=!0,e.elements.parentMenu.currentEvent=e.currentEvent,e.elements.parentMenu.currentChild=t),t++}}p("number",{value:e}),e<-1?(this._currentChild=-1,t(this)):e>=this.elements.menuItems.length?(this._currentChild=this.elements.menuItems.length-1,t(this)):this.focusChild!==e&&(this._currentChild=e,t(this))}},{key:"focusState",get:function(){return this._focusState},set:function(t){!function(t){try{if("object"!==e(t)){var n=e(t);throw new TypeError("AccessibleMenu: Values given to isValidState() must be inside of an object. ".concat(n," given."))}var o=["none","self","child"];for(var s in t)if(!o.includes(t[s]))throw new TypeError("AccessibleMenu: ".concat(s," must be one of the following values: ").concat(o.join(", "),'. "').concat(t[s],'" given.'))}catch(e){return console.error(e),!1}}({value:t}),this._focusState!==t&&(this._focusState=t),this.elements.submenuToggles.length>0&&("self"===t||"none"===t)&&this.elements.submenuToggles.forEach((function(e){e.elements.controlledMenu.focusState="none"})),!this.elements.parentMenu||"self"!==t&&"child"!==t||(this.elements.parentMenu.focusState="child")}},{key:"currentEvent",get:function(){return this._currentEvent},set:function(t){!function(t){try{if("object"!==e(t)){var n=e(t);throw new TypeError("AccessibleMenu: Values given to isValidEvent() must be inside of an object. ".concat(n," given."))}var o=["none","mouse","keyboard","character"];for(var s in t)if(!o.includes(t[s]))throw new TypeError("AccessibleMenu: ".concat(s," must be one of the following values: ").concat(o.join(", "),'. "').concat(t[s],'" given.'))}catch(e){return console.error(e),!1}}({value:t}),this._currentEvent!==t&&(this._currentEvent=t,this.elements.submenuToggles.length>0&&this.elements.submenuToggles.forEach((function(e){e.elements.controlledMenu.currentEvent=t})))}},{key:"currentMenuItem",get:function(){return this.elements.menuItems[this.currentChild]}},{key:"hoverType",get:function(){return this._root?this._hoverType:this.elements.rootMenu.hoverType},set:function(e){g({value:e}),this._hoverType!==e&&(this._hoverType=e)}},{key:"hoverDelay",get:function(){return this._root?this._hoverDelay:this.elements.rootMenu.hoverDelay},set:function(e){p("number",{value:e}),this._hoverDelay!==e&&(this._hoverDelay=e)}},{key:"shouldFocus",get:function(){var e=!1;return"keyboard"!==this.currentEvent&&"character"!==this.currentEvent||(e=!0),"mouse"===this.currentEvent&&"dynamic"===this.hoverType&&(e=!0),e}},{key:"_validate",value:function(){var e=!0;return null!==this._dom.container||null!==this._dom.controller?d(HTMLElement,{menuElement:this._dom.menu,controllerElement:this._dom.controller,containerElement:this._dom.container})||(e=!1):d(HTMLElement,{menuElement:this._dom.menu})||(e=!1),""!==this._selectors.submenuItems?v({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks,submenuItemSelector:this._selectors.submenuItems,submenuToggleSelector:this._selectors.submenuToggles,submenuSelector:this._selectors.submenus})||(e=!1):v({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks})||(e=!1),""===this._openClass||y({openClass:this._openClass})||(e=!1),""===this._closeClass||y({closeClass:this._closeClass})||(e=!1),p("boolean",{isTopLevel:this._root})||(e=!1),null===this._elements.parentMenu||d(n,{parentMenu:this._elements.parentMenu})||(e=!1),g({hoverType:this._hoverType})||(e=!1),p("number",{hoverDelay:this._hoverDelay})||(e=!1),e}},{key:"_setDOMElementType",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.dom.menu,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if("string"!=typeof this.selectors[e])throw new Error('AccessibleMenu: "'.concat(e,'" is not a valid element type within the menu.'));if(!Array.isArray(this.dom[e]))throw new Error('AccessibleMenu: The "'.concat(e,'" element cannot be set through _setDOMElementType.'));t!==this.dom.menu&&d(HTMLElement,{base:t});var o=Array.from(t.querySelectorAll(this.selectors[e])),s=o.filter((function(e){return e.parentElement===t}));this._dom[e]=n?s:[].concat(h(this._dom[e]),h(s))}},{key:"_resetDOMElementType",value:function(e){if(void 0===this.dom[e])throw new Error('AccessibleMenu: "'.concat(e,'" is not a valid element type within the menu.'));if(!Array.isArray(this.dom[e]))throw new Error('AccessibleMenu: The "'.concat(e,'" element cannot be reset through _resetDOMElementType.'));this._dom[e]=[]}},{key:"_setDOMElements",value:function(){var e=this;this._setDOMElementType("menuItems"),""!==this.selectors.submenuItems&&(this._setDOMElementType("submenuItems"),this._resetDOMElementType("submenuToggles"),this._resetDOMElementType("submenus"),this.dom.submenuItems.forEach((function(t){e._setDOMElementType("submenuToggles",t,!1),e._setDOMElementType("submenus",t,!1)})))}},{key:"_findRootMenu",value:function(e){if(e.isTopLevel)this._elements.rootMenu=e;else{if(null===e.elements.parentMenu)throw new Error("Cannot find root menu.");this._findRootMenu(e.elements.parentMenu)}}},{key:"_createChildElements",value:function(){var e=this;this.dom.menuItems.forEach((function(t){var n;if(e.dom.submenuItems.includes(t)){var o=t.querySelector(e.selectors.submenuToggles),s=t.querySelector(e.selectors.submenus),r=new e._MenuType({menuElement:s,menuItemSelector:e.selectors.menuItems,menuLinkSelector:e.selectors.menuLinks,submenuItemSelector:e.selectors.submenuItems,submenuToggleSelector:e.selectors.submenuToggles,submenuSelector:e.selectors.submenus,openClass:e.openClass,closeClass:e.closeClass,isTopLevel:!1,parentMenu:e,hoverType:e.hoverType,hoverDelay:e.hoverDelay}),l=new e._MenuToggleType({menuToggleElement:o,parentElement:t,controlledMenu:r,parentMenu:e});e._elements.submenuToggles.push(l),n=new e._MenuItemType({menuItemElement:t,menuLinkElement:o,parentMenu:e,isSubmenuItem:!0,childMenu:r,toggle:l})}else{var i=t.querySelector(e.selectors.menuLinks);n=new e._MenuItemType({menuItemElement:t,menuLinkElement:i,parentMenu:e})}e._elements.menuItems.push(n)}))}},{key:"_handleFocus",value:function(){var e=this;this.elements.menuItems.forEach((function(t,n){t.dom.link.addEventListener("focus",(function(){e.focusState="self",e.currentChild=n}))}))}},{key:"_handleClick",value:function(){var e=this,t=b("touchstart",this.dom.menu)?"touchstart":"mousedown",n=b("touchend",this.dom.menu)?"touchend":"mouseup";function o(e,t,n){C(n),t.toggle(),t.isOpen&&(e.focusState="self",t.elements.controlledMenu.focusState="none")}this.elements.menuItems.forEach((function(s,r){s.dom.link.addEventListener(t,(function(){e.currentEvent="mouse",e.elements.rootMenu.blurChildren(),e.focusChild(r)})),s.isSubmenuItem&&(s.elements.toggle.dom.toggle["on".concat(n)]=function(t){e.currentEvent="mouse",o(e,s.elements.toggle,t)})})),this.isTopLevel&&this.elements.controller&&(this.elements.controller.dom.toggle["on".concat(n)]=function(t){e.currentEvent="mouse",o(e,e.elements.controller,t)})}},{key:"_handleHover",value:function(){var e=this;this.elements.menuItems.forEach((function(t,n){t.dom.link.addEventListener("mouseenter",(function(){if("on"===e.hoverType)e.currentEvent="mouse",e.currentChild=n,t.isSubmenuItem&&t.elements.toggle.preview();else if("dynamic"===e.hoverType){var o=e.elements.submenuToggles.some((function(e){return e.isOpen}));e.currentChild=n,e.isTopLevel&&"none"===e.focusState||(e.currentEvent="mouse",e.focusCurrentChild()),!t.isSubmenuItem||e.isTopLevel&&!o||(e.currentEvent="mouse",t.elements.toggle.preview())}})),t.isSubmenuItem&&t.dom.item.addEventListener("mouseleave",(function(){"on"===e.hoverType?e.hoverDelay>0?setTimeout((function(){e.currentEvent="mouse",t.elements.toggle.close()}),e.hoverDelay):(e.currentEvent="mouse",t.elements.toggle.close()):"dynamic"===e.hoverType&&(e.isTopLevel||(e.hoverDelay>0?setTimeout((function(){e.currentEvent="mouse",t.elements.toggle.close(),e.focusCurrentChild()}),e.hoverDelay):(e.currentEvent="mouse",t.elements.toggle.close(),e.focusCurrentChild())))}))}))}},{key:"_handleKeydown",value:function(){var e=this;this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keydown",(function(t){e.currentEvent="keyboard";var n=E(t);"Space"!==n&&"Enter"!==n||C(t)}))}},{key:"_handleKeyup",value:function(){var e=this;this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keyup",(function(t){e.currentEvent="keyboard";var n=E(t);"Space"!==n&&"Enter"!==n||(C(t),e.elements.controller.open(),e.focusFirstChild())}))}},{key:"focus",value:function(){this.focusState="self",this.shouldFocus&&this.dom.menu.focus()}},{key:"blur",value:function(){this.focusState="none",this.shouldFocus&&this.dom.menu.blur()}},{key:"focusCurrentChild",value:function(){this.focusState="self",-1!==this.currentChild&&this.currentMenuItem.focus()}},{key:"focusChild",value:function(e){this.blurCurrentChild(),this.currentChild=e,this.focusCurrentChild()}},{key:"focusFirstChild",value:function(){this.focusChild(0)}},{key:"focusLastChild",value:function(){this.focusChild(this.elements.menuItems.length-1)}},{key:"focusNextChild",value:function(){this.currentChild<this.elements.menuItems.length-1?this.focusChild(this.currentChild+1):this.focusCurrentChild()}},{key:"focusPreviousChild",value:function(){this.currentChild>0?this.focusChild(this.currentChild-1):this.focusCurrentChild()}},{key:"blurCurrentChild",value:function(){this.focusState="none",-1!==this.currentChild&&this.currentMenuItem.blur()}},{key:"focusController",value:function(){this.dom.controller&&(this.shouldFocus&&this.dom.controller.focus(),this.focusState="none")}},{key:"focusContainer",value:function(){this.dom.container&&(this.shouldFocus&&this.dom.container.focus(),this.focusState="none")}},{key:"closeChildren",value:function(){this.elements.submenuToggles.forEach((function(e){return e.close()}))}},{key:"blurChildren",value:function(){this.elements.menuItems.forEach((function(e){e.blur(),e.isSubmenuItem&&e.elements.childMenu.blurChildren()}))}}]),n}(),k=function(e){r(o,e);var n=a(o);function o(e){var s,r=e.menuItemElement,l=e.menuLinkElement,i=e.parentMenu,u=e.isSubmenuItem,c=void 0!==u&&u,a=e.childMenu,m=void 0===a?null:a,h=e.toggle,f=void 0===h?null:h,d=e.initialize,p=void 0===d||d;return t(this,o),s=n.call(this,{menuItemElement:r,menuLinkElement:l,parentMenu:i,isSubmenuItem:c,childMenu:m,toggle:f}),p&&s.initialize(),s}return o}(M),w=function(e){r(s,e);var n=a(s);function s(e){var o,r=e.menuToggleElement,l=e.parentElement,i=e.controlledMenu,u=e.parentMenu,c=void 0===u?null:u,a=e.initialize,m=void 0===a||a;return t(this,s),o=n.call(this,{menuToggleElement:r,parentElement:l,controlledMenu:i,parentMenu:c}),m&&o.initialize(),o}return o(s,[{key:"open",value:function(){this.closeSiblings(),m(l(s.prototype),"open",this).call(this)}},{key:"preview",value:function(){this.closeSiblings(),m(l(s.prototype),"preview",this).call(this)}},{key:"close",value:function(){this.isOpen&&this.closeChildren(),m(l(s.prototype),"close",this).call(this)}}]),s}(_);return function(e){r(i,e);var n=a(i);function i(e){var o,r=e.menuElement,l=e.menuItemSelector,c=void 0===l?"li":l,a=e.menuLinkSelector,m=void 0===a?"a":a,h=e.submenuItemSelector,f=void 0===h?"":h,d=e.submenuToggleSelector,p=void 0===d?"a":d,v=e.submenuSelector,y=void 0===v?"ul":v,g=e.controllerElement,b=void 0===g?null:g,_=e.containerElement,M=void 0===_?null:_,E=e.openClass,C=void 0===E?"show":E,T=e.closeClass,S=void 0===T?"hide":T,I=e.isTopLevel,L=void 0===I||I,A=e.parentMenu,O=void 0===A?null:A,D=e.hoverType,j=void 0===D?"off":D,R=e.hoverDelay,z=void 0===R?250:R,K=e.optionalKeySupport,x=void 0!==K&&K,F=e.initialize,H=void 0===F||F;return t(this,i),s(u(o=n.call(this,{menuElement:r,menuItemSelector:c,menuLinkSelector:m,submenuItemSelector:f,submenuToggleSelector:p,submenuSelector:y,controllerElement:b,containerElement:M,openClass:C,closeClass:S,isTopLevel:L,parentMenu:O,hoverType:j,hoverDelay:z})),"_MenuType",i),s(u(o),"_MenuItemType",k),s(u(o),"_MenuToggleType",w),s(u(o),"_currentChild",-1),s(u(o),"_optionalSupport",!1),o._optionalSupport=x,H&&o.initialize(),o}return o(i,[{key:"initialize",value:function(){try{m(l(i.prototype),"initialize",this).call(this),this._handleFocus(),this._handleClick(),this._handleHover(),this._handleKeydown(),this._handleKeyup()}catch(e){console.error(e)}}},{key:"optionalKeySupport",get:function(){return this.isTopLevel?this._optionalSupport:this.elements.rootMenu.optionalKeySupport},set:function(e){p("boolean",{optionalKeySupport:e}),this._optionalSupport=e}},{key:"_validate",value:function(){var e=m(l(i.prototype),"_validate",this).call(this);return p("boolean",{optionalKeySupport:this._optionalSupport})||(e=!1),e}},{key:"_handleClick",value:function(){var e=this;m(l(i.prototype),"_handleClick",this).call(this);var t=b("touchend",this.dom.menu)?"touchend":"mouseup";document.addEventListener(t,(function(t){"none"!==e.focusState&&(e.currentEvent="mouse",e.dom.menu.contains(t.target)||!e.dom.menu===t.target||(e.closeChildren(),e.blur(),e.elements.controller&&e.elements.controller.close()))}))}},{key:"_handleKeydown",value:function(){var e=this;m(l(i.prototype),"_handleKeydown",this).call(this),this.dom.menu.addEventListener("keydown",(function(t){e.currentEvent="keyboard";var n=E(t);if("self"===e.focusState){if(e.optionalKeySupport){["ArrowUp","ArrowRight","ArrowDown","ArrowLeft","Home","End"].includes(n)&&C(t)}else(e.currentMenuItem.isSubmenuItem&&["Space","Enter"].includes(n)||e.elements.controller&&["Escape"].includes(n)||e.elements.parentMenu&&["Escape"].includes(n))&&C(t)}}))}},{key:"_handleKeyup",value:function(){var e=this;m(l(i.prototype),"_handleKeyup",this).call(this),this.dom.menu.addEventListener("keyup",(function(t){e.currentEvent="keyboard";var n=E(t);if("self"===e.focusState)if("Space"===n||"Enter"===n)e.currentMenuItem.isSubmenuItem?(C(t),e.currentMenuItem.elements.toggle.preview()):e.currentMenuItem.dom.link.click();else if("Escape"===n){e.elements.submenuToggles.some((function(e){return e.isOpen}))?(C(t),e.closeChildren()):e.elements.parentMenu?(C(t),e.elements.parentMenu.currentEvent=e.currentEvent,e.elements.parentMenu.closeChildren(),e.elements.parentMenu.focusCurrentChild()):e.isTopLevel&&e.elements.controller&&e.elements.controller.isOpen&&(e.elements.controller.close(),e.focusController())}else e.optionalKeySupport&&("ArrowDown"===n||"ArrowRight"===n?(C(t),e.currentMenuItem.isSubmenuItem&&e.currentMenuItem.elements.toggle.isOpen?(e.currentMenuItem.elements.childMenu.currentEvent="keyboard",e.currentMenuItem.elements.childMenu.focusFirstChild()):e.focusNextChild()):"ArrowUp"===n||"ArrowLeft"===n?(C(t),e.focusPreviousChild()):"Home"===n?(C(t),e.focusFirstChild()):"End"===n&&(C(t),e.focusLastChild()))}))}}]),i}(T)}();
//# sourceMappingURL=disclosure-menu.min.js.map
document.addEventListener("DOMContentLoaded", () => {
const containerElement = document.querySelector("nav");
const controllerElement = containerElement.querySelector("button");
const menuElement = containerElement.querySelector("ul");
const menu = new DisclosureMenu({
menuElement,
submenuItemSelector: ".dropdown",
containerElement,
controllerElement,
optionalKeySupport: true,
});
});