Vertical menu collapsible v2

by Plippie Plop

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<header><button type="button" class="btn" id="toggle-aside"><i class="fa fa-bars"></i></button></header>
<aside>
  <header>
    <h3>Header</h3>
  </header>
  <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>
          <li><a>Item 3 sub 3</a>
          <li><a>Item 3 sub 4</a>
          <li><a>Item 3 sub 5</a>
          <li><a>Item 3 sub 6</a>
        </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>
</aside>

CSS

@import url('https://fonts.googleapis.com/css2?family=Noto+Sans&family=Oswald&display=swap');

:root {
  --menu-bg: rgb(250, 250, 250);
  --menu-item-bg: rgb(255, 255, 255);
  --menu-item-hover-bg: rgb(242, 242, 245);
  --menu-item-active-bg: rgb(124 192 251);
  --menu-item-active-hover-bg: rgb(171 214 251);
  --menu-color: rgb(20,20,20);
  --menu-active-color: rgb(255,255,255);
  --menu-border-radius: 0;
  --menu-sub-height: 20em;
  
  /* using font awesome 4.7 for chevron icons */
}

* {
  box-sizing: border-box;
  margin:0;
  padding:0;
}

body{
font-family:Oswald;
}

body > header{
  display:flex;
  
}

#toggle-aside{
  position:fixed;
  left:10px;
  top:10px;
}
 aside{
  position:absolute;
  left:0;
  top:0;
  bottom:0;
  background-color:lightgrey;
  display:flex;
  flex-direction:column;
   transition: transform 0.2s ease-in-out;
    transform:translateX(0);
}
.aside-close aside{
  transform:translateX(-50px);
}
aside header{
  display:flex;
  align-items:center;
  flex:0 0 auto;
  padding:0.5rem;
}
aside header h3{
 flex:1 1 auto;
 font-size:1rem; 
 
}

ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
  position: relative;
  outline: none;
  overflow: hidden;
}

#list {
  display: flex;
  position: relative;
  flex:1 1 auto;
  overflow-y:auto;
  width:100%;
  width: fit-content;
  font-family: "Oswald";
  border-radius: var(--menu-border-radius);
  min-width: 200px;
  box-shadow: -5px 5px 11px 0 rgba(0, 0, 0, 0.18);
}

#list ::-webkit-scrollbar {
  width: 0.25rem;
}

#list ::-webkit-scrollbar-track {
  background: var(--memu-bg);
}

#list ::-webkit-scrollbar-thumb {
  background: rgba(100, 100, 100, 0.4);
  border-radius: 2px;
}

#list ::-webkit-scrollbar-thumb:hover {
  background: rgba(100, 100, 100, 0.8);
}

.menu {
  width: 100%;
}

.menu ul {
  max-height: 0;
  transition: max-height 0.2s;
  height: auto;
  background-color: var(--menu-bg);


}

.menu li.open>ul {
  transition: max-height 0.2s;
  max-height: var(--menu-sub-height);
 ...

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');
  }

});

$('#toggle-aside').on('click', function() {
  $('body').toggleClass('aside-close');
});