JSFiddle - React, Tailwind, and code Playground
by Plippie Plop
HTML
<nav id="list">
<ul class="menu">
<li class="first-menu"><a>Item 1</a></li>
<li class="first-menu"><a>Item 2</a>
<ul>
<li><a>item 2 sub 1</a></li>
<li><a>Item 2 sub 2</a></li>
</ul>
</li>
<li class="first-menu"><a>Item 3</a>
<ul>
<li><a>item 3 sub 1</a></li>
<li><a>Item 3 sub 2</a>
<ul>
<li><a>Item 2 sub-sub 1</a></li>
<li><a>Item 2 sub-sub 2</a></li>
</ul>
</li>
</ul>
</li>
<li class="first-menu"><a>Item 4</a>
<ul>
<li><a>item 4 sub 1</a></li>
<li><a>Item 4 sub 2</a>
<ul>
<li><a>Item 4 sub-sub 1</a></li>
<li><a>Item 4 sub-sub 2</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
CSS
@import url('https://fonts.googleapis.com/css2?family=Oswald&display=swap');
* {
box-sizing: border-box;
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
position: relative;
outline: none;
}
#list {
display: flex;
background-color: lightgrey;
position: relative;
width: auto;
font-family: "Oswald";
padding: 0.5rem;
}
.menu a {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
padding: 0.5rem 1.5rem 0.5rem 0.5rem;
background-color: white;
min-width: 150px;
cursor: pointer;
position: relative;
}
.menu a:hover {
background-color: rgba(0, 0, 0, 0.02);
}
.menu li a.active {
background-color: rgb(124 192 251);
}
.menu a.active:hover{
background-color:rgba(124 192 251, 0.5);
}
.menu .open a.active {
background-color: rgb(155 209 255);
}
#list .first-menu:first-of-type > a {
border-radius: 0.25rem 0.25rem 0 0;
}
#list .first-menu:last-of-type > a {
border-radius: 0 0 0.25rem 0.25rem;
border-bottom: 0;
}
#list .has-sub>a::after {
position: absolute;
right: 0;
top: 0;
transform: translateY(50%);
content: "▼";
color: grey;
padding: 0.25rem;
font-size: 0.6rem;
}
#list .has-sub.open>ul>li>a {
background-color: rgb(155 209 255);
}
#list .has-sub.open .open>ul>li>a {
background-color: rgb(178 220 255);
}
#list .has-sub.open>a::after {
content: "▲";
}
#list .has-sub.open>a::before {
content: '';
position: absolute;
z-index: 1;
top: 99%;
left: 0;
right: 0;
margin: 0 auto;
width: 0;
height: 0;
border-top: solid 0.3rem rgba(0, 0, 0, 0.5);
border-left: solid 0.3rem rgba(0, 0, 0, 0);
border-right: solid 0.3rem rgba(0, 0, 0, 0);
}
#list .menu ul {
overflow: hidden;
max-height: 0;
transition: max-height 0.2s;
}
#list .menu li.open>ul {
max-height: 10em;
transition: max-height 0.2s;
}
JavaScript
const list = $("#list");
list.find('a').each(function(idx, elm) {
console.log(idx, elm);
$(elm).closest('li').attr('data-menu-index', idx);
if ($(elm).closest('li').children('ul').length) {
$(elm).closest('li').addClass('has-sub');
}
});
list.find('.active').parents('li').addClass('open').find('> a').addClass('active');
list.on('click', 'a', function(e) {
let $this = $(this);
if (!$this.hasClass('active')) {
console.log("not active");
list.find('.open').removeClass('open');
list.find('.active').removeClass('active');
$this.addClass('active').parents('li').addClass('open').find('> a').addClass('active');
} else {
console.log("IS active");
$this.removeClass('active').closest('li').removeClass('open');
$this.children('li').removeClass('open');
}
});