Responsive Details-Summary Menu

A mobile-responsive multi-level click-down menu using Details-Summary...

Expand and contract this window around the 640px width mark...

The CSS...

<style>

/* The mobile nav styles */

/* Enforce list semantics */
nav [role="list"] {
  list-style: none;
  padding-left: 1rem;
}

nav details {
  display: inline-block;
}

@media (min-width: 40em) { /* 640px */

  /* Note: dropdowns may use position absolute,
      but was considered beyond scope in this simple demo. */

  nav > details > [role="list"] {
    display: flex;
    gap: 1rem;
    margin-top: 0 !important;
    padding: 0;
  }
  nav > details > ul > li {
    margin-top: 0 !important;
  }
}
</style>

The HTML...

<nav>
    <details>
      <summary>Mobile menu</summary>
      <ul role=list>
        <li><a href="#">About us</a></li>
        <li>
          <details>
            <summary>Products</summary>
            <ul role=list>
              <li><a href="#">Product 1</a></li>
              <li><a href="#">Product 2</a></li>
              <li>
                <details>
                  <summary>Sub</summary>
                  <ul role=list>
                    <li><a href="#">Sub 1</a></li>
                    <li><a href="#">Sub 2</a></li>
                  </ul>
                </details>
              </li>
            </ul>
          </details>
        </li>
        <li><a href="#">Insights</a></li>
        <li><a href="#">Contact</a></li>
      </ul>
    </details>
  </nav>

The Javascript...

<script>
    console.clear();

// The mobile disclosure button only:
// Progressive enhancement, works without JS too.

const responsiveMenuButton = (document => {
  'use strict';

  const minViewportWidth = '40em'; // @ 640px

  const details = document.querySelector('nav > details');
  if (!details) return;

  const summary = details.querySelector('summary');
  if (!summary) return;

  const mediaQuery = window.matchMedia(`(min-width: ${minViewportWidth})`);
  let isSmallScreen = !mediaQuery.matches;

  const showMenu = _ => {

    // Edge case: Orientation may change viewport width without moving focus
    const isSummaryFocused = !!details.querySelector('summary:is(:focus)');

    details.open = true;
    summary.hidden = true;

    if (isSummaryFocused) {
      const firstLink = details.querySelector('a[href]');
      firstLink && firstLink.focus();
    }
  };

  const hideMenu = _ => {

    // Edge case: Orientation may change viewport width without moving focus
    const isMenuLinkFocused = !!details.querySelector('ul:is(:focus-within)');

    details.removeAttribute('open');
    summary.removeAttribute('hidden');

    isMenuLinkFocused && summary.focus();
  };

  const controlResponsiveMenu = event => {
    if (isSmallScreen && event.matches) {
      showMenu();
      isSmallScreen = true;
    }

    isSmallScreen && !event.matches && hideMenu();

    !isSmallScreen && event.matches && showMenu();

    if (!isSmallScreen && !event.matches) {
      hideMenu();
      isSmallScreen = false;
    }
  };

  mediaQuery.addListener(controlResponsiveMenu);
  controlResponsiveMenu(mediaQuery);
})(document);
</script>

From https://codepen.io/2kool2/pen/JjaLLWb