JSFiddle - React, Tailwind, and code Playground
by Plippie Plop
HTML
<div class="menu">
<ul role="menu">
<li><a href="#" tabindex="0">Item</a></li>
<li><a href="#" tabindex="0" aria-haspopup="true" aria-expanded="false">Item <span aria-hidden="true">▾</span></a>
<ul role="menu">
<li><a href="#" tabindex="0">Sub Item</a></li>
<li><a href="#" tabindex="0">Sub Item</a></li>
</ul>
</li>
<li><a href="#" tabindex="0">Item</a></li>
<li><a href="#" tabindex="0">Item</a></li>
<li><a href="#" tabindex="0">Item</a></li>
<li><a href="#" tabindex="0">Item</a></li>
<li><a href="#" tabindex="0" aria-haspopup="true" aria-expanded="false">Item <span aria-hidden="true">▾</span></a>
<ul role="menu">
<li><a href="#" tabindex="0">Sub Item</a></li>
<li><a href="#" tabindex="0">Sub Item</a></li>
<li><a href="#" tabindex="0" aria-haspopup="true" aria-expanded="false">Item <span aria-hidden="true">▾</span></a>
<ul role="menu">
<li><a href="#" tabindex="0">SubSub Item</a></li>
<li><a href="#" tabindex="0">SubSub Item</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
CSS
.menu ul,
.menu li {
padding: 0;
margin: 0;
list-style: none;
}
.menu li:focus{
outline:0;
}
.menu a {
text-decoration: none;
display: block;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.menu>ul li ul {
display: none;
}
.menu a[aria-expanded="true"] + ul{
display:block;
}
.menu>ul li:hover{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.menu a:focus{
outline:0;
border-radius:3px;
border:1px solid grey;
}
.menu [aria-expanded="true"] + ul li a{
background-color:grey;
}
JavaScript
const $menu = document.querySelector('.menu > ul');
const menuItems = $menu.querySelectorAll('a');
Array.prototype.forEach.call(menuItems, function(el, i) {
el.addEventListener("click", function(event) {
console.log(this, event);
closeSiblings(this);
if (this.getAttribute("aria-expanded") === "false") {
this.setAttribute('aria-expanded', "true");
} else {
this.setAttribute('aria-expanded', "false");
}
event.preventDefault();
return false;
});
});
const closeSiblings = function (elem) {
// Setup siblings array and get the first sibling
const siblings = elem.closest('.menu');
const openSibs = siblings.querySelectorAll('a[aria-expanded="true"]');
console.log(openSibs);
for (const item of openSibs) {
if(item !== elem){
console.log("found open");
item.setAttribute('aria-expanded', "false");
}
}
};