<header class="dropdown-nav" aria-label="Main Menu Navigation">
    <div class="dropdown-nav__inner">
        <nav class="dropdown-nav__menu" role="navigation">
            <div class="dropdown-nav__toggle-container">
                <button class="btn dropdown-nav__toggle" aria-haspopup="true" aria-expanded="false" aria-controls="main-menu" data-nav-toggle>Menu</button>
            </div>
            <div class="dropdown-nav__list-container" data-nav-list-container>
                <ul class="dropdown-nav__list" id="main-menu" aria-label="Main Menu Items" data-nav-list>
                    <li class="dropdown-nav__item" data-dropdown-item>
                        <a href="/" class="dropdown-nav__link" aria-controls="lorem-submenu" data-dropdown-link data-has-popup>
                Lorem
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
                        <button class="sub-nav__toggle" aria-controls="lorem-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
                        <div class="dropdown-nav__sub-list-container" data-sub-list-container>
                            <ul class="dropdown-nav__sub-list" id="lorem-submenu" aria-label="Lorem Submenu" data-sub-list>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Lorem</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Set</a>
                                </li>
                            </ul>
                        </div>
                    </li>
                    <li class="dropdown-nav__item" data-dropdown-item>
                        <a href="/" class="dropdown-nav__link" data-dropdown-link>Ipsum</a>
                    </li>
                    <li class="dropdown-nav__item" data-dropdown-item>
                        <a href="/" class="dropdown-nav__link" data-dropdown-link>Dolar</a>
                    </li>
                    <li class="dropdown-nav__item" data-dropdown-item>
                        <a href="/" class="dropdown-nav__link" aria-controls="amet-submenu" data-dropdown-link data-has-popup>Amet
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
                        <button class="sub-nav__toggle" aria-controls="amet-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
                        <div class="dropdown-nav__sub-list-container" data-sub-list-container>
                            <ul class="dropdown-nav__sub-list" id="amet-submenu" aria-label="Amet Submenu" data-sub-list>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Lorem</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                                </li>
                            </ul>
                        </div>
                    </li>
                    <li class="dropdown-nav__item" data-dropdown-item>
                        <a href="/" class="dropdown-nav__link" aria-controls="faucibus-submenu" data-dropdown-link data-has-popup>Faucibus
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
                        <button class="sub-nav__toggle" aria-controls="faucibus-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
                        <div class="dropdown-nav__sub-list-container" data-sub-list-container>
                            <ul class="dropdown-nav__sub-list" id="faucibus-submenu" aria-label="Faucibus Submenu" data-sub-list>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                                </li>
                                <li class="dropdown-nav__sub-item">
                                    <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                                </li>
                            </ul>
                        </div>
                    </li>
                </ul>
            </div>
            <!-- /.container -->
        </nav>
    </div>
</header>
<header class="dropdown-nav" aria-label="Main Menu Navigation">
  <div class="dropdown-nav__inner">
    <nav class="dropdown-nav__menu" role="navigation">
      <div class="dropdown-nav__toggle-container">
        <button class="btn dropdown-nav__toggle" aria-haspopup="true" aria-expanded="false" aria-controls="main-menu" data-nav-toggle>Menu</button>
      </div>
      <div class="dropdown-nav__list-container" data-nav-list-container>
        <ul class="dropdown-nav__list" id="main-menu" aria-label="Main Menu Items" data-nav-list>
          <li class="dropdown-nav__item" data-dropdown-item>
            <a href="/" class="dropdown-nav__link" aria-controls="lorem-submenu" data-dropdown-link data-has-popup>
                Lorem
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
            <button class="sub-nav__toggle" aria-controls="lorem-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
            <div class="dropdown-nav__sub-list-container" data-sub-list-container>
              <ul class="dropdown-nav__sub-list" id="lorem-submenu" aria-label="Lorem Submenu" data-sub-list>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Lorem</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Set</a>
                </li>
              </ul>
            </div>
          </li>
          <li class="dropdown-nav__item" data-dropdown-item>
            <a href="/" class="dropdown-nav__link" data-dropdown-link>Ipsum</a>
          </li>
          <li class="dropdown-nav__item" data-dropdown-item>
            <a href="/" class="dropdown-nav__link" data-dropdown-link>Dolar</a>
          </li>
          <li class="dropdown-nav__item" data-dropdown-item>
            <a href="/" class="dropdown-nav__link" aria-controls="amet-submenu" data-dropdown-link data-has-popup>Amet
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
            <button class="sub-nav__toggle" aria-controls="amet-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
            <div class="dropdown-nav__sub-list-container" data-sub-list-container>
              <ul class="dropdown-nav__sub-list" id="amet-submenu" aria-label="Amet Submenu" data-sub-list>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Lorem</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                </li>
              </ul>
            </div>
          </li>
          <li class="dropdown-nav__item" data-dropdown-item>
            <a href="/" class="dropdown-nav__link" aria-controls="faucibus-submenu"data-dropdown-link data-has-popup>Faucibus
              <svg class="dropdown-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </a>
            <button class="sub-nav__toggle" aria-controls="faucibus-submenu" data-subnav-toggle>
              <span class="u-sr-only">Toggle Subnav</span>
              <svg class="sub-nav__arrow" viewBox="0 0 407.437 407.437" role="presentation" aria-hidden="true">
                  <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "/>
              </svg>
            </button>
            <div class="dropdown-nav__sub-list-container" data-sub-list-container>
              <ul class="dropdown-nav__sub-list" id="faucibus-submenu" aria-label="Faucibus Submenu" data-sub-list>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Ipsum</a>
                </li>
                <li class="dropdown-nav__sub-item">
                  <a href="/" class="dropdown-nav__sub-link">Dolar</a>
                </li>
              </ul>
            </div>
          </li>
        </ul>
      </div>
      <!-- /.container -->
    </nav>
  </div>
</header>
/* No context defined for this component. */
  • Content:
    .dropdown-nav {
      border-bottom: 1px solid color(neutral, lighter);
      background-color: color(neutral, lightest);
    
      &__inner {
        display: flex;
        margin: 0 auto;
        padding: 0;
        width: 100%;
        max-width: 1200px;
      }
    
      &__menu {
        width: 100%;
    
        @media (min-width: $breakpoint-md) {
          margin: 0 auto;
          width: auto;
        }
      }
    
      &__toggle-container {
        display: flex;
    
        @media (min-width: $breakpoint-md) { display: none; }
      }
    
      &__toggle {
        margin-left: auto;
        border-radius: 0;
        background-color: transparent;
        color: $text-color;
    
        &:focus { z-index: 1; }  // to see full focus outline
      }
    
      &__list-container {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 0;
        overflow: hidden;
        visibility: hidden;
        transition: height .2s ease-in-out, visibility .2s ease-in-out;
    
        @media (min-width: $breakpoint-md) {
          height: auto;
          overflow: visible;
          visibility: visible;
        }
    
        &.is-open {
          height: 100vh;
          overflow: auto;
          visibility: visible;
        }
      }
    
      &__list {
        margin: 0;
        padding: 0;
        width: 100%;
        overflow: hidden;
        transition: height .2s ease-in-out, visibility .2s ease-in-out;
    
        @media (min-width: $breakpoint-md) {
          margin: 0 auto;
          width: auto;
          height: auto;
          overflow: visible;
        }
      }
    
      &__item {
        position: relative;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: space-between;
        margin: 0;
        border-top: 1px solid color(neutral, lighter);
        border-right: 1px solid color(neutral, lighter);
        border-left: 1px solid color(neutral, lighter);
        background-color: color(neutral, lightest);
    
        &:last-child {
          border-bottom: 1px solid color(neutral, lighter);
    
          @media (min-width: $breakpoint-md) { border: 0; }
        }
    
        @media (min-width: $breakpoint-md) {
          display: inline-block;
          border: 0;
          padding: $base-spacing 0;
    
          &:focus,
          &:focus-within,
          &:hover,
          &.is-hovered {
    
            &__sub-list-container {
              opacity: 1;
              visibility: visible;
            }
          }
        }
    
        .sub-nav__toggle {
          display: block;
          border: 0;
          border-left: 1px solid color(neutral, lighter);
          padding: 20px;
          background-color: color(neutral, lightest);
    
          &:focus { z-index: 1; } // to see full focus outline
    
          @media (min-width: $breakpoint-md) { display: none; }
        }
    
        .sub-nav__arrow {
          display: block;
          width: 20px;
          height: 20px;
          pointer-events: none;
          transition: .2s ease-in-out;
    
          &.is-active { transform: rotate(180deg); }
        }
      }
    
      &__item + &__item {
        list-style: none;
    
        @media (min-width: $breakpoint-md) { margin-left: 40px; }
      }
    
      &__link {
        @include font-size(18);
    
        display: flex;
        flex: 1;
        align-items: center;
        justify-content: space-between;
        padding: 15px 0 15px 15px;
        width: auto;
    
        @media (min-width: $breakpoint-md) {
          display: inline-flex;
          line-height: 1;
        }
      }
    
      &__link.is-open + button + &__sub-list-container {
        opacity: 1;
        visibility: visible;
      }
    
    &__sub-list-container {
        margin: 0;
        padding: 0;
        width: 100%;
        height: 0;
        overflow: hidden;
        transition: height .2s ease-in-out, visibility .2s ease-in-out;
    
        @media (min-width: $breakpoint-md) {
          position: absolute;
          top: 100%;
          left: 0;
          display: block;
          margin: 0;
          border: 1px solid #dcdcdc;
          border-top: 0;
          width: 180px;
          height: auto;
          overflow: visible;
          background-color: #f4f4f4;
          opacity: 0;
          visibility: hidden;
        }
    
        &.is-open { height: auto; }
      }
    
      &__sub-list {
        display: flex;
        flex-direction: column;
        margin: 0;
        padding: 0;
        width: 100%;
        overflow: hidden;
        background-color: color(neutral, lightest);
        transition: height .2s ease-in-out, visibility .2s ease-in-out;
    
        @media (min-width: $breakpoint-md) {
          margin: 0;
          border-top: 0;
          padding: 10px;
          height: auto;
          max-height: none;
          background-color: color(neutral, lightest);
          visibility: visible;
          transition: none;
        }
    
        .is-open & { border-top: 1px solid color(neutral, lighter); }
      }
    
      &__sub-item {
        @include font-size(16);
    
        display: block;
        margin: 0;
        border-bottom: 1px solid color(neutral, lighter);
        padding: 15px 0 15px 60px;
        background-color: color(neutral, lightest);
        list-style: none;
    
        &:last-child { border-bottom: 0; }
    
        @media (min-width: $breakpoint-md) {
          border: 0;
          padding: 0;
        }
      }
    
      &__sub-item + &__sub-item {
    
        @media (min-width: $breakpoint-md) { margin-top: 10px; }
      }
    
      &__arrow {
        display: none;
        pointer-events: none;
        transition: .2s ease-in-out;
    
        @media (min-width: $breakpoint-md) {
          display: block;
          margin-right: 0;
          margin-left: 10px;
          width: 10px;
          height: 10px;
        }
      }
    }
    
  • URL: /components/raw/dropdown-nav/_dropdown-nav.scss
  • Filesystem Path: components/dropdown-nav/_dropdown-nav.scss
  • Size: 5 KB
  • Content:
     const mobileBreakpointMax = 768;
    const windowWidth = window.innerWidth || document.documentElement.clientWidth;
    const dropdownItems = document.querySelectorAll('[data-dropdown-item]');
    const navContainer = document.querySelector('[data-nav-list-container]');
    const mainMenuToggle = document.querySelector('[data-nav-toggle]');
    const mainMenu = document.querySelector('[data-nav-list]');
    const subNavContainers = document.querySelectorAll('[data-sub-list-container]');
    const subNavContainer = document.querySelector('[data-sub-list-container]');
    const subMenuToggles = document.querySelectorAll('[data-subnav-toggle]');
    const subMenuLinks = document.querySelectorAll('[data-has-popup]');
    const subMenuArrows = document.querySelectorAll('.sub-nav__arrow');
    const hoveredClassName = 'is-hovered';
    
    // set aria attributes on buttons on mobile, links on desktop
    function setAriaAttributes() {
    
      if (windowWidth < mobileBreakpointMax) {
        for (let i = 0; i < subMenuLinks.length; i++) {
          subMenuLinks[i].removeAttribute('aria-has-popup', 'false');
          subMenuLinks[i].removeAttribute('aria-expanded', 'false');
        }
        for (let i = 0; i < subMenuToggles.length; i++) {
          subMenuToggles[i].setAttribute('aria-has-popup', 'true');
          subMenuToggles[i].setAttribute('aria-expanded', 'false');
        }
      } else {
        for (let i = 0; i < subMenuLinks.length; i++) {
          subMenuLinks[i].setAttribute('aria-has-popup', 'true');
          subMenuLinks[i].setAttribute('aria-expanded', 'false');
        }
        for (let i = 0; i < subMenuToggles.length; i++) {
          subMenuToggles[i].removeAttribute('aria-has-popup', 'false');
          subMenuToggles[i].removeAttribute('aria-expanded', 'false');
        }
      }
    }
    
    function handleMobileNav() {
    
      // open/close top level menu on mobile
      mainMenuToggle.addEventListener('click', function(e) {
        const toggleExpanded = (e.target.getAttribute('aria-expanded') === 'true') ? false : true;
    
        mainMenuToggle.setAttribute('aria-expanded', toggleExpanded);
    
        if (navContainer.classList.contains('is-open')) {
          navContainer.classList.remove('is-open');
    
          //when main menu is closed, also close all submenus
          for (let i = 0; i < subMenuToggles.length; i++) {
            if (subMenuToggles[i].classList.contains('is-open')) {
              subNavContainer.classList.remove('is-open');
            }
          }
    
        } else {
          navContainer.classList.add('is-open');
        }
    
      });
    
      // open/close sub-level menus on mobile using buttons
      for (let i = 0; i < subMenuToggles.length; i++) {
        
        subMenuToggles[i].addEventListener('click', function(e) {
          const subNavContainer = subMenuToggles[i].nextElementSibling;
          const subNavParent = subNavContainer.parentElement;
          const subMenuHeight = e.target.nextElementSibling.firstElementChild.offsetHeight;
          const subToggleIcon = e.target.querySelector('.sub-nav__arrow');
    
          // rotate arrow icon
          subToggleIcon.classList.add('is-active');
    
          if(subNavParent.classList.contains('is-open')) {
            subNavParent.classList.remove('is-open');
            subToggleIcon.classList.remove('is-active');
            subNavContainer.setAttribute('style', 'height: 0; visibility: hidden;');
            subMenuToggles[i].setAttribute('aria-expanded', 'false');
          } else {
            subNavParent.classList.add('is-open');
            subToggleIcon.classList.add('is-active');
            subNavContainer.setAttribute('style', `height: ${subMenuHeight}px; visibility: visible;`);
            subMenuToggles[i].setAttribute('aria-expanded', 'true');
          }
    
        });
      }
    };
    
    // handle touchscreens in landscape orientation where desktop version of menu is displayed
    function handleTabletTouch() {
      
      for (let i = 0; i < subMenuLinks.length; i++) { 
    
        subMenuLinks[i].addEventListener('touchstart', function(e) {
            const currentTarget = e.currentTarget;
            const previousCurrentTarget = document.querySelectorAll('.is-hovered');
    
            currentTarget.parentElement.classList.add('is-hovered');
            currentTarget.setAttribute('aria-expanded', 'true');
            
            for (let i = 0; i < previousCurrentTarget.length; i++) {
              previousCurrentTarget[i].classList.remove('is-hovered');
              previousCurrentTarget[i].firstElementChild.setAttribute('aria-expanded', 'false');
            }
    
            e.preventDefault();
        });
      }
    }
    
    function collapseSubNav() {
    
      if (navContainer.classList.contains('is-open')) {
        navContainer.classList.remove('is-open');
      }
    
      for (let i = 0; i < dropdownItems.length; i++) {
        dropdownItems[i].classList.remove('is-open');
        dropdownItems[i].classList.remove('is-hovered');
      }
    
      for (let i = 0; i < subMenuArrows.length; i++) {
        subMenuArrows[i].classList.remove('is-active'); 
      }
    
      for (let i = 0; i < subMenuLinks.length; i++) {
        subMenuLinks[i].classList.remove('is-open'); 
      }
    
      for (let i = 0; i < subNavContainers.length; i++) {
        subNavContainers[i].setAttribute('style', '');
      }
    } 
    
    // Utility function to make window resizing more performant.
    function debounce(func, wait = 100) {
      let timeout;
      return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          func.apply(this, args);
        }, wait);
      };
    }
    
    document.addEventListener('DOMContentLoaded', function() {
    
      setAriaAttributes();
      handleMobileNav();
    
      // Set listeners for mouse and focus events
      if (windowWidth > mobileBreakpointMax) {
        for (let i = 0; i < subMenuLinks.length; i++) {
          const linkWithSubmenu = subMenuLinks[i].parentElement;
          const link = subMenuLinks[i];
    
          linkWithSubmenu.addEventListener('focusin', () => {
            link.setAttribute('aria-expanded', 'true');
            link.classList.add('is-open');
          });
    
          linkWithSubmenu.addEventListener('focusout', () => {
            link.setAttribute('aria-expanded', 'false');
            link.classList.remove('is-open');
          });
    
          linkWithSubmenu.addEventListener('mouseenter', () => {
            subMenuLinks[i].setAttribute('aria-expanded', 'true');
            subMenuLinks[i].classList.add('is-open');
          });
    
          linkWithSubmenu.addEventListener('mouseleave', () => {
            subMenuLinks[i].setAttribute('aria-expanded', 'false');
            subMenuLinks[i].classList.remove('is-open');
          });
        }
      }
    
      // Arrow key controls
      for (let i = 0; i < dropdownItems.length; i++) {
        dropdownItems[i].addEventListener('keydown', (e) => {
    
          if (e.keyCode === 37) {
            if (i === 0) {
              dropdownItems[dropdownItems.length - 1]
                .querySelector('[data-dropdown-link]')
                .focus();
            } else {
              dropdownItems[i - 1]
                .querySelector('[data-dropdown-link]')
                .focus();
            }
          }
    
          if (e.keyCode === 39) {
            if (i === dropdownItems.length - 1) {
              dropdownItems[0]
                .querySelector('[data-dropdown-link]')
                .focus();
            } else {
              dropdownItems[i + 1]
                .querySelector('[data-dropdown-link]')
                .focus();
            }
          }
        });
      }
    
      window.addEventListener('resize', debounce(function() {
        const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
        
        collapseSubNav();
    
        //reset aria attributes based on vieportWidth after resize
        if (viewportWidth < mobileBreakpointMax) {
          for (let i = 0; i < subMenuLinks.length; i++) {
            subMenuLinks[i].removeAttribute('aria-has-popup', 'false');
            subMenuLinks[i].removeAttribute('aria-expanded');
          }
          for (let i = 0; i < subMenuToggles.length; i++) {
            subMenuToggles[i].setAttribute('aria-has-popup', 'true');
            subMenuToggles[i].setAttribute('aria-expanded', 'false');
          }
        } else {
          for (let i = 0; i < subMenuLinks.length; i++) {
            subMenuLinks[i].setAttribute('aria-has-popup', 'true');
            subMenuLinks[i].setAttribute('aria-expanded', 'false');
          }
          for (let i = 0; i < subMenuToggles.length; i++) {
            subMenuToggles[i].removeAttribute('aria-has-popup', 'false');
            subMenuToggles[i].removeAttribute('aria-expanded', 'false');
          }
        } 
    
        if (viewportWidth >= mobileBreakpointMax  && viewportWidth <= 1367) {
          handleTabletTouch();
        }
        
      }));
    });
    
  • URL: /components/raw/dropdown-nav/dropdown-nav.js
  • Filesystem Path: components/dropdown-nav/dropdown-nav.js
  • Size: 8.3 KB

Usage

Dropdown navigation presents a list of options to a user when activated by hovering or focusing on the parent links.

This Dropdown Navigation comes with two configuration attributes. The data-dropdown-item attribute is used to flag top level navigation list items, and the data-dropdown-link attribute is used to flag thier respective child main link. This assists in identification for the cooresponding Javascript keyboard functionality.

Labelling Expectations

  • If a navigation item has a nested list, the aria-expanded="false" attribute should be added as a default state. When activated, the attribute should change to aria-expanded="true".
  • If a navigation item has a nested list, it should include an aria-label="submenu name" attribute.
  • The dropdown menu visibility should be toggled using the hidden attribute.

Focus Expectations

  • Each nav item has a focus state. If there is a nested list, the list is expanded on focus and the sub items are then added to the tab index.

Screen Reader Expectations

When interacting with dropdown navigation, screen readers should announce the following:

  • Main Menu
  • Menu items, total number of list items
  • If there is a nested list, this will be announced as a popup list
  • Current state of menu link - expanded or collapsed

Keyboard Expectations

  • Tab = Move to next focusable element
  • Tab = Expand/collapse dropdown
  • = Cycle through top level links when top level links are focused

Tab Order Expectations

When navigating through dropdown menu navigation, the following tab order is expected:

  1. Top level menu items
  2. If there is a nested list, the sub-items are added to the tablist