Skip to main content

Your privacy settings

We use cookies to help you with journey planning and relevant disruptions, remember your login and show you content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.

Manage Cookies
Beta

This is a new service - your feedback will help us to improve it.

Patterns

Header

About

What does it do?

  • The primary way of navigating the website
  • Standardised pattern

When to use it?

  • Every page must have a header and a footer


Header

Skip link

There is a hidden skip link for users with screen reader assistive technology. This allows users to quickly access the main content. All pages must include this.

Ensure there is a HTML element on the page with the ID of wmnds-main-content so the user can skip to this section.

Logo

This must always be the Transport for West Midlands logo.

Phase indicator

This component must be used if the service is not live, using the phase indicator guidance.

Navigation

The three top-level navigation items were decided by identifying our user’s top tasks using Gerry McGovern’s methodology. We overlaid a heatmap of the home page, where we found the same three areas were the most-used areas.

The top-level items open a structured megamenu to avoid cognitive overload. Users are familiar with this pattern from online shopping and transport operators.

We only use three top-level items as we prefer not to use hamburger menus on mobile. Users are required to make an extra click to reveal the navigation, therefore you cannot glance at navigation options.

Mobile apps

When designing an app, you should use a tab bar and avoid using hamburger items wherever possible. Limit the tabs to the most important tasks using user research.

Search

This function expands the mega menu and reveals the search bar along with the ‘I want to…’ feature.

The ‘I want to...’ feature shows a list of the top page links which users access through search. This is to help users find the information they are searching for faster. These links are regularly updated using search data to maintain their relevance.

On mobile, the mega menu search function uses a primary purple background instead of the standard white background. Our user testing found users preferred the white link text on the primary purple background as it is clearer to read.



HTML markup
<!-- Skip to content link -->
<a href="#wmnds-main-content" title="Skip to main content" target="_self" class="wmnds-link wmnds-header__skip-link">
  Skip to main content
</a>
<!-- Main header section -->
<header>
  <div class="wmnds-bg-white wmnds-p-t-md wmnds-p-b-md wmnds-cookies-banner">
    <div class="wmnds-container">
      <div class="wmnds-col-1 wmnds-col-md-3-4 wmnds-col-lg-2-3">
        <h3>Your privacy settings</h3>
        <p>
          We use cookies to help you with journey planning and relevant disruptions, remember your login and show you
          content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority
          and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.
        </p>
        <div class="wmnds-grid wmnds-grid--justify-between wmnds-cookies-banner__group-buttons">
          <button class="wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24  wmnds-cookies-banner__accept-all-cookies wmnds-text-align-center" type="button">
            Accept all cookies
          </button>
          <a href="https://www.tfwm.org.uk/manage-cookies/" title="link title" target="_self" class="wmnds-btn wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24 wmnds-text-align-center">
            Manage Cookies
          </a>
        </div>
      </div>
    </div>
  </div>
  <div class="wmnds-header wmnds-header--mega-menu">
    <div class="wmnds-container wmnds-grid wmnds-grid--align-center wmnds-grid--justify-between">
      <div class="wmnds-header__vertical-align wmnds-col-auto">
        <!-- Logo -->
        <a class="wmnds-header__logo-link" href="/" title="Transport for West Midlands Design System">
          <img class="wmnds-header__logo" alt="Transport for West Midlands logo" src="/img/logo.svg" />
        </a>
      </div>
      <!-- Mega menu nav items-->
      <nav id="mega-menu-example-full" class="wmnds-mega-menu">
        <!-- Mobile toggle button -->
        <button class="wmnds-mega-menu__mobile-toggle wmnds-btn wmnds-btn--secondary wmnds-hide-desktop" aria-expanded="false" aria-controls="mega-menu-example-full-primary-menu">Menu
          <svg class="wmnds-mega-menu__close-icon">
            <use xlink:href="#wmnds-general-cross" href="#wmnds-general-cross"></use>
          </svg>
        </button>
        <!-- Container for mega menu - allows scrolling on mobile nav -->
        <div id="mega-menu-example-full-primary-menu" class="wmnds-mega-menu__scroll-controller">
          <!-- Start primary (level 1) navigation -->
          <ul class="wmnds-mega-menu__primary-menu">
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                Styles
              </button>
            </li>
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                Components
              </button>
            </li>
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                Patterns
              </button>
            </li>
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                User research
              </button>
            </li>
          </ul>
          <!-- End primary (level 1) navigation -->
        </div>
        <!-- End scrollable container -->
      </nav>
    </div>
  </div>
  <div class="wmnds-container">
    <!-- Phase banner -->
    <div class="wmnds-banner-container">
      <div class="wmnds-col-1">
        <div class="wmnds-banner-container__phase-wrapper">
          <span class="wmnds-phase-indicator">
            Beta
          </span>
        </div>
        <p class="wmnds-banner-container__text">
          This is a new service - your
          <a href="https://github.com/wmcadigital/wmn-design-system/issues" title="WMN Design System Github" target="_blank" class="wmnds-link" rel="noopener noreferrer">
            feedback
          </a>
          will help us to improve it.
        </p>
      </div>
    </div>
    <!-- Breadcrumbs -->
    <nav aria-label="Breadcrumbs" class="wmnds-breadcrumb">
      <ol class="wmnds-breadcrumb__list">
        <li class="wmnds-breadcrumb__list-item">
          <a href="/" class="wmnds-breadcrumb__link">
            Home
          </a>
        </li>
        <li class="wmnds-breadcrumb__list-item">
          <a href="/patterns" class="wmnds-breadcrumb__link">
            Patterns
          </a>
        </li>
        <li class="wmnds-breadcrumb__list-item">
          <a href="/patterns/header" class="wmnds-breadcrumb__link wmnds-breadcrumb__link--current" aria-current="page">
            Header
          </a>
        </li>
      </ol>
    </nav>
  </div>
</header>

Recommended javascript (browser compatible)
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var headerJs = function headerJs() {
  // get mega menu elements
  var megaMenus = document.querySelectorAll('.wmnds-mega-menu');
  var mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  var getMenuLink = function getMenuLink(currentIndex, array, direction) {
    var menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  var setKeyboardNavigation = function setKeyboardNavigation(subMenuContainer, subMenuQuery, onFirst, onLast) {
    // array of all links in menu container
    var allLinksArray = [];

    // use specified query to select all submenus
    var subMenus = subMenuContainer.querySelectorAll(subMenuQuery);
    subMenus.forEach(function(subMenu, subMenuIndex) {
      var thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach(function(link, linkIndex) {
        link.addEventListener('keydown', function(e) {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              var nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              var prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || e.keyCode === 9 && !e.shiftKey) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              var nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ? getMenuLink(linkIndex, thisSubMenuLinks, 'next') : getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');
              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || e.shiftKey && e.keyCode === 9) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              var prevMenu = allLinksArray[subMenuIndex - 1];
              var prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ? getMenuLink(linkIndex, thisSubMenuLinks, 'prev') : getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };
  megaMenus.forEach(function(menu) {
    var clearActiveListItems = function clearActiveListItems() {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(function(menuItem) {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    var setMenuActive = function setMenuActive(element) {
      var active = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var onCloseFocusElement = arguments.length > 2 ? arguments[2] : undefined;
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        var mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        var headerEl = menu.parentNode.parentNode;
        var topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        var searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        var mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', function() {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });
        if (searchBtn) {
          searchBtn.addEventListener('click', function() {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(function(menuBtn) {
          var handleSubMenus = function handleSubMenus() {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            var targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        var collapseMenus = menu.querySelectorAll('.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle');
        collapseMenus.forEach(function(collapseToggle) {
          var handleThirdLevelMenus = function handleThirdLevelMenus() {
            var panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = "".concat(panel.scrollHeight, "px");
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);
    var topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    var menuDelay = false;
    var enterTimeOut;
    var leaveTimeOut;
    var delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach(function(topLevelLink, topLevelLinkIndex) {
      // return list item parent of the current link if it exists else return the link
      var topLevelListItem = topLevelLink.parentNode.tagName === 'LI' || topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ? topLevelLink.parentNode : topLevelLink;
      var subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      var hasSubmenuChildren = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(function(subMenu) {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }
      var openSubMenu = function openSubMenu(e) {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };
      var handleKeydown = function handleKeydown(e, key) {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          var prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          var nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      var isTopLevelWithMenu = topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length;
      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', function() {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            enterTimeOut = setTimeout(function() {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem.querySelector('.wmnds-mega-menu__container').addEventListener('mouseover', function() {
          if (menuDelay) {
            // if container is rehovered before timeout is done, clear all timeouts kill the delay
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            menuDelay = false;
          }
        });
        topLevelListItem.addEventListener('mouseleave', function() {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(function() {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });
        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }
      topLevelListItem.addEventListener('keydown', function(e) {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', function(e) {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', function(e) {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      var subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');
      if (subMenuContainer) {
        setKeyboardNavigation(subMenuContainer, '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          function() {
            return topLevelLink.focus();
          },
          // what to do on last link
          function() {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          });
      }
    });

    // set up keyboard navigation for search menu links
    var searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(searchMenuContainer, '.wmnds-search-list',
        // what to do on first link
        function() {
          return menu.querySelector('.wmnds-search-bar__input').focus();
        },
        // what to do on last link
        function() {
          return setMenuActive(menu.querySelector('.wmnds-mega-menu__search'), false, menu.querySelector('.wmnds-mega-menu__search-btn'));
        });
    }
  });
};
var _default = headerJs;
exports["default"] = _default;

Recommended javascript (ES6)
const headerJs = () => {
  // get mega menu elements
  const megaMenus = document.querySelectorAll('.wmnds-mega-menu');

  const mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  const getMenuLink = (currentIndex, array, direction) => {
    let menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  const setKeyboardNavigation = (subMenuContainer, subMenuQuery, onFirst, onLast) => {
    // array of all links in menu container
    const allLinksArray = [];

    // use specified query to select all submenus
    const subMenus = subMenuContainer.querySelectorAll(subMenuQuery);

    subMenus.forEach((subMenu, subMenuIndex) => {
      const thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach((link, linkIndex) => {
        link.addEventListener('keydown', e => {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              const nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              const prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              const nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ?
                getMenuLink(linkIndex, thisSubMenuLinks, 'next') :
                getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');

              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || (e.shiftKey && e.keyCode === 9)) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              const prevMenu = allLinksArray[subMenuIndex - 1];
              let prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ?
                  getMenuLink(linkIndex, thisSubMenuLinks, 'prev') :
                  getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };

  megaMenus.forEach(menu => {
    const clearActiveListItems = () => {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(menuItem => {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    const setMenuActive = (element, active = true, onCloseFocusElement) => {
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        const mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        const headerEl = menu.parentNode.parentNode;

        const topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        const searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        const mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', () => {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove(
              'wmnds-header--mega-menu-open',
              'wmnds-header--mega-menu-submenu-open'
            );
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });

        if (searchBtn) {
          searchBtn.addEventListener('click', () => {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove(
                'wmnds-header--mega-menu-open',
                'wmnds-header--mega-menu-submenu-open'
              );
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(menuBtn => {
          const handleSubMenus = () => {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            const targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        const collapseMenus = menu.querySelectorAll(
          '.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle'
        );
        collapseMenus.forEach(collapseToggle => {
          const handleThirdLevelMenus = () => {
            const panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = `${panel.scrollHeight}px`;
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);

    const topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    let menuDelay = false;
    let enterTimeOut;
    let leaveTimeOut;
    const delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach((topLevelLink, topLevelLinkIndex) => {
      // return list item parent of the current link if it exists else return the link
      const topLevelListItem =
        topLevelLink.parentNode.tagName === 'LI' ||
        topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ?
        topLevelLink.parentNode :
        topLevelLink;

      const subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      const hasSubmenuChildren =
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(subMenu => {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }

      const openSubMenu = e => {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };

      const handleKeydown = (e, key) => {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          const prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          const nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      const isTopLevelWithMenu = topLevelListItem.querySelectorAll(
        '.wmnds-mega-menu__container'
      ).length;

      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', () => {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);

            enterTimeOut = setTimeout(() => {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem
          .querySelector('.wmnds-mega-menu__container')
          .addEventListener('mouseover', () => {
            if (menuDelay) {
              // if container is rehovered before timeout is done, clear all timeouts kill the delay
              clearTimeout(enterTimeOut);
              clearTimeout(leaveTimeOut);
              menuDelay = false;
            }
          });
        topLevelListItem.addEventListener('mouseleave', () => {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(() => {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });

        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }

      topLevelListItem.addEventListener('keydown', e => {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', e => {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', e => {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      const subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');

      if (subMenuContainer) {
        setKeyboardNavigation(
          subMenuContainer,
          '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          () => topLevelLink.focus(),
          // what to do on last link
          () => {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          }
        );
      }
    });

    // set up keyboard navigation for search menu links
    const searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(
        searchMenuContainer,
        '.wmnds-search-list',
        // what to do on first link
        () => menu.querySelector('.wmnds-search-bar__input').focus(),
        // what to do on last link
        () =>
        setMenuActive(
          menu.querySelector('.wmnds-mega-menu__search'),
          false,
          menu.querySelector('.wmnds-mega-menu__search-btn')
        )
      );
    }
  });
};

export default headerJs;

Mega menu with search example



HTML markup
<!-- Skip to content link -->
<a href="#wmnds-main-content" title="Skip to main content" target="_self" class="wmnds-link wmnds-header__skip-link">
  Skip to main content
</a>
<!-- Main header section -->
<header>
  <div class="wmnds-bg-white wmnds-p-t-md wmnds-p-b-md wmnds-cookies-banner">
    <div class="wmnds-container">
      <div class="wmnds-col-1 wmnds-col-md-3-4 wmnds-col-lg-2-3">
        <h3>Your privacy settings</h3>
        <p>
          We use cookies to help you with journey planning and relevant disruptions, remember your login and show you
          content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority
          and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.
        </p>
        <div class="wmnds-grid wmnds-grid--justify-between wmnds-cookies-banner__group-buttons">
          <button class="wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24  wmnds-cookies-banner__accept-all-cookies wmnds-text-align-center" type="button">
            Accept all cookies
          </button>
          <a href="https://www.tfwm.org.uk/manage-cookies/" title="link title" target="_self" class="wmnds-btn wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24 wmnds-text-align-center">
            Manage Cookies
          </a>
        </div>
      </div>
    </div>
  </div>
  <div class="wmnds-header wmnds-header--mega-menu">
    <div class="wmnds-container wmnds-grid wmnds-grid--align-center wmnds-grid--justify-between">
      <div class="wmnds-header__vertical-align wmnds-col-auto">
        <!-- Logo -->
        <a class="wmnds-header__logo-link" href="/" title="Transport for West Midlands Design System">
          <img class="wmnds-header__logo" alt="Transport for West Midlands logo" src="/img/logo.svg" />
        </a>
      </div>
      <!-- Mega menu nav items-->
      <nav id="mega-menu-example" class="wmnds-mega-menu">
        <!-- Mobile toggle button -->
        <button class="wmnds-mega-menu__mobile-toggle wmnds-btn wmnds-btn--secondary wmnds-hide-desktop" aria-expanded="false" aria-controls="mega-menu-example-primary-menu">Menu
          <svg class="wmnds-mega-menu__close-icon">
            <use xlink:href="#wmnds-general-cross" href="#wmnds-general-cross"></use>
          </svg>
        </button>
        <!-- Container for mega menu - allows scrolling on mobile nav -->
        <div id="mega-menu-example-primary-menu" class="wmnds-mega-menu__scroll-controller">
          <!-- Start primary (level 1) navigation -->
          <ul class="wmnds-mega-menu__primary-menu">
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                Plan a journey
              </button>
              <!-- arrow icon for mobile nav -->
              <button class="wmnds-mega-menu__link-arrow-icon-btn" data-label="Plan a journey" aria-label="toggle Plan a journey" aria-controls="mega-menu-example-container"><svg class="wmnds-mega-menu__link-arrow-icon">
                  <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                </svg></button>
              <!-- Start mega menu container -->
              <div id="mega-menu-example-container-1" class="wmnds-mega-menu__container">
                <div class="wmnds-container">
                  <!-- Start submenu (level 2) -->
                  <ul class="wmnds-mega-menu__sub-menu">
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/plan-a-journey/plan-your-journey/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-route" href="#wmnds-general-route"></use>
                        </svg>
                        Plan your journey</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Plan your journey menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-plan-your-journey-1" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/plan-your-journey/journey-planner/" class="wmnds-mega-menu__sub-menu-child-link">Journey planner</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/plan-your-journey/find-a-timetable/" class="wmnds-mega-menu__sub-menu-child-link">Find a timetable</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/plan-your-journey/live-and-planned-disruptions/" class="wmnds-mega-menu__sub-menu-child-link">Live and planned disruptions</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/plan-your-journey/major-roadworks-and-events/" class="wmnds-mega-menu__sub-menu-child-link">Major roadworks and events</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/plan-a-journey/ways-to-travel/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-location-arrow" href="#wmnds-general-location-arrow"></use>
                        </svg>
                        Ways to travel</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Ways to travel menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-ways-to-travel-2" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/walking/" class="wmnds-mega-menu__sub-menu-child-link">Walking</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/cycling/" class="wmnds-mega-menu__sub-menu-child-link">Cycling</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/buses/" class="wmnds-mega-menu__sub-menu-child-link">Buses</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/trains/" class="wmnds-mega-menu__sub-menu-child-link">Trains</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/trams/" class="wmnds-mega-menu__sub-menu-child-link">Trams</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/park-and-ride/" class="wmnds-mega-menu__sub-menu-child-link">Park and ride</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/ways-to-travel/driving/" class="wmnds-mega-menu__sub-menu-child-link">Driving</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/plan-a-journey/travel-information/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-info" href="#wmnds-general-info"></use>
                        </svg>
                        Travel information</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Travel information menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-travel-information-3" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/travel-information/how-to-travel-with-accessibility-needs/" class="wmnds-mega-menu__sub-menu-child-link">How to travel with accessibility needs</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/travel-information/how-to-travel-safely/" class="wmnds-mega-menu__sub-menu-child-link">How to travel safely</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/travel-information/how-to-get-to-hospital/" class="wmnds-mega-menu__sub-menu-child-link">How to get to hospital</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/plan-a-journey/discover-our-region/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-star" href="#wmnds-general-star"></use>
                        </svg>
                        Discover our region</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Discover our region menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-discover-our-region-4" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/discover-our-region/places-and-attractions-to-visit/" class="wmnds-mega-menu__sub-menu-child-link">Places and attractions to visit</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/plan-a-journey/discover-our-region/find-discount-vouchers/" class="wmnds-mega-menu__sub-menu-child-link">Find discount vouchers</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                  </ul>
                  <!-- End submenu (level 2) -->
                </div>
              </div>
              <!-- End mega menu container -->
            </li>
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                <svg class="wmnds-swift-icon">
                  <title>Swift</title>
                  <use xlink:href="#wmnds-swift-full-logo" href="#wmnds-swift-full-logo"></use>
                </svg>
                and tickets
              </button>
              <!-- arrow icon for mobile nav -->
              <button class="wmnds-mega-menu__link-arrow-icon-btn" data-label="Swift and tickets" aria-label="toggle Swift and tickets" aria-controls="mega-menu-example-container"><svg class="wmnds-mega-menu__link-arrow-icon">
                  <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                </svg></button>
              <!-- Start mega menu container -->
              <div id="mega-menu-example-container-2" class="wmnds-mega-menu__container">
                <div class="wmnds-container">
                  <!-- Start submenu (level 2) -->
                  <ul class="wmnds-mega-menu__sub-menu">
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/swift-and-tickets/find-a-ticket/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-search" href="#wmnds-general-search"></use>
                        </svg>
                        Find a ticket</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Find a ticket menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-find-a-ticket-1" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/find-a-ticket/ticket-finder/" class="wmnds-mega-menu__sub-menu-child-link">Ticket finder</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/find-a-ticket/types-of-ticket/" class="wmnds-mega-menu__sub-menu-child-link">Types of ticket</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/swift-and-tickets/discounts-and-free-travel-passes/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-wallet" href="#wmnds-general-wallet"></use>
                        </svg>
                        Discounts and free travel passes</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Discounts and free travel passes menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-discounts-and-free-travel-passes-2" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/under-18s/" class="wmnds-mega-menu__sub-menu-child-link">Under 18s</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/students/" class="wmnds-mega-menu__sub-menu-child-link">Students</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/families-and-groups/" class="wmnds-mega-menu__sub-menu-child-link">Families and groups</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/finding-or-starting-a-new-job/" class="wmnds-mega-menu__sub-menu-child-link">Finding or starting a new job</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/disabled-person&#39;s-pass/" class="wmnds-mega-menu__sub-menu-child-link">Disabled person&#39;s pass</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/older-person&#39;s-pass/" class="wmnds-mega-menu__sub-menu-child-link">Older person&#39;s pass</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/discounts-and-free-travel-passes/waspi-women&#39;s-pass/" class="wmnds-mega-menu__sub-menu-child-link">Waspi women&#39;s pass</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/swift-and-tickets/manage-your-swift-card/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-swift-bird-icon" href="#wmnds-swift-bird-icon"></use>
                        </svg>
                        Manage your <svg class="wmnds-swift-icon">
                          <title>Swift</title>
                          <use xlink:href="#wmnds-swift-full-logo" href="#wmnds-swift-full-logo"></use>
                        </svg> card</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Manage your Swift card menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-manage-your-swift-card-3" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/how-to-use-your-swift-card/" class="wmnds-mega-menu__sub-menu-child-link">How to use your swift card</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/update-your-personal-details/" class="wmnds-mega-menu__sub-menu-child-link">Update your personal details</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/top-up-your-swift-card/" class="wmnds-mega-menu__sub-menu-child-link">Top up your swift card</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/view-your-payment-history/" class="wmnds-mega-menu__sub-menu-child-link">View your payment history</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/view-your-travel-history/" class="wmnds-mega-menu__sub-menu-child-link">View your travel history</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-swift-card/replace-your-lost-swift-card/" class="wmnds-mega-menu__sub-menu-child-link">Replace your lost swift card</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/swift-and-tickets/manage-your-ticket/" class="wmnds-mega-menu__sub-menu-link">
                        <!-- Show submenu (level 2) item icon if specified -->
                        <svg class="wmnds-mega-menu__sub-menu-link-icon">
                          <use xlink:href="#wmnds-general-ticket" href="#wmnds-general-ticket"></use>
                        </svg>
                        Manage your ticket</a>
                      <!-- collapse button for mobile nav level 3 menu items -->
                      <button class="wmnds-mega-menu__collapse-toggle" aria-expanded="false" aria-label="Toggle Manage your ticket menu" aria-controls="mega-menu-example-submenu-child-menu"><svg class="wmnds-mega-menu__link-arrow-icon">
                          <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg></button>
                      <!-- Start submenu child (level 3) list -->
                      <ul id="mega-menu-example-submenu-child-menu-manage-your-ticket-4" class="wmnds-mega-menu__sub-menu-child-menu">
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-ticket/update-your-direct-debit/" class="wmnds-mega-menu__sub-menu-child-link">Update your direct debit</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-ticket/get-a-refund/" class="wmnds-mega-menu__sub-menu-child-link">Get a refund</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-ticket/make-a-payment/" class="wmnds-mega-menu__sub-menu-child-link">Make a payment</a>
                        </li>
                        <li class="wmnds-mega-menu__sub-menu-child-item">
                          <a href="/swift-and-tickets/manage-your-ticket/replace-your-lost-ticket-or-pass/" class="wmnds-mega-menu__sub-menu-child-link">Replace your lost ticket or pass</a>
                        </li>
                      </ul>
                      <!-- End submenu child (level 3) list -->
                    </li>
                  </ul>
                  <!-- End submenu (level 2) -->
                </div>
              </div>
              <!-- End mega menu container -->
            </li>
            <li class="wmnds-mega-menu__primary-menu-item">
              <!-- Show swift logo in nav if is swift & tickets link -->
              <!-- allow primary (level 1) item to link if specified -->
              <button target="_self" class="wmnds-mega-menu__primary-menu-link">
                Get help
              </button>
              <!-- arrow icon for mobile nav -->
              <button class="wmnds-mega-menu__link-arrow-icon-btn" data-label="Get help" aria-label="toggle Get help" aria-controls="mega-menu-example-container"><svg class="wmnds-mega-menu__link-arrow-icon">
                  <use xlink-href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                </svg></button>
              <!-- Start mega menu container -->
              <div id="mega-menu-example-container-3" class="wmnds-mega-menu__container">
                <div class="wmnds-container">
                  <!-- Start submenu (level 2) -->
                  <ul class="wmnds-mega-menu__sub-menu">
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/contact-an-operator/" class="wmnds-mega-menu__sub-menu-link">
                        Contact an operator</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/find-a-travel-centre/" class="wmnds-mega-menu__sub-menu-link">
                        Find a travel centre</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/find-lost-property/" class="wmnds-mega-menu__sub-menu-link">
                        Find lost property</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/give-feedback/" class="wmnds-mega-menu__sub-menu-link">
                        Give feedback</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/contact-us/" class="wmnds-mega-menu__sub-menu-link">
                        Contact us</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/report-anti-social-behaviour/" class="wmnds-mega-menu__sub-menu-link">
                        Report anti-social behaviour</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/request-a-new-bus-shelter-or-stop-pole/" class="wmnds-mega-menu__sub-menu-link">
                        Request a new bus shelter or stop pole</a>
                    </li>
                    <li class="wmnds-mega-menu__sub-menu-item">
                      <a href="/get-help/report-a-problem-with-a-shelter-or-stop/" class="wmnds-mega-menu__sub-menu-link">
                        Report a problem with a shelter or stop</a>
                    </li>
                  </ul>
                  <!-- End submenu (level 2) -->
                </div>
              </div>
              <!-- End mega menu container -->
            </li>
          </ul>
          <!-- End primary (level 1) navigation -->
        </div>
        <!-- End scrollable container -->
        <div class="wmnds-mega-menu__primary-menu-item wmnds-mega-menu__search">
          <button class="wmnds-mega-menu__primary-menu-link wmnds-mega-menu__search-btn">
            <svg class="wmnds-mega-menu__search-icon">
              <title>Search</title>
              <use xlink:href="#wmnds-general-search" href="#wmnds-general-search"></use>
            </svg>
            <svg class="wmnds-mega-menu__search-close-icon">
              <title>Close</title>
              <use xlink:href="#wmnds-general-cross" href="#wmnds-general-cross"></use>
            </svg>
          </button>
          <div class="wmnds-mega-menu__container wmnds-mega-menu__search-container">
            <div class="wmnds-search-container">
              <form id="searchBar_form" class="wmnds-search-bar">
                <input id="searchBar_input" aria-label="Search" type="text" class="wmnds-search-bar__input wmnds-fe-input" placeholder="Search for tickets, timetables, travel advice…">
                <button class="wmnds-search-bar__btn" type="submit">
                  <svg>
                    <title>Search</title>
                    <use xlink:href="#wmnds-general-search" href="#wmnds-general-search"></use>
                  </svg>
                </button>
              </form>
              <p class="wmnds-search-heading wmnds-h1">I want to...</p>
              <div class="wmnds-grid">
                <div class="wmnds-col-1-2">
                  <ul class="wmnds-search-list">
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">See live departures
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Find a timetable
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Check for disruptions
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Manage my Swift card
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                  </ul>
                </div>
                <div class="wmnds-col-1-2">
                  <ul class="wmnds-search-list">
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Find ticket prices
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Get a refund
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Update Direct Debit
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                    <li class="wmnds-search-list__item">
                      <a href="#" class="wmnds-link wmnds-link--with-chevron">Apply for a 16-18 photocard
                        <svg class="wmnds-link__chevron wmnds-link__chevron--right">
                          <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
                        </svg>
                      </a>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
          </div>
        </div>
      </nav>
    </div>
  </div>
</header>
<!-- Content space for example purposes only. DO NOT INCLUDE -->
<div class="demo-content">
  <p>Example content <br> <a href="/patterns/header-demo" target="_blank">View full page example (opens in new window)</a></p>
</div>
<!-- END DO NOT INCLUDE -->

Recommended javascript (browser compatible)
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var headerJs = function headerJs() {
  // get mega menu elements
  var megaMenus = document.querySelectorAll('.wmnds-mega-menu');
  var mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  var getMenuLink = function getMenuLink(currentIndex, array, direction) {
    var menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  var setKeyboardNavigation = function setKeyboardNavigation(subMenuContainer, subMenuQuery, onFirst, onLast) {
    // array of all links in menu container
    var allLinksArray = [];

    // use specified query to select all submenus
    var subMenus = subMenuContainer.querySelectorAll(subMenuQuery);
    subMenus.forEach(function(subMenu, subMenuIndex) {
      var thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach(function(link, linkIndex) {
        link.addEventListener('keydown', function(e) {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              var nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              var prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || e.keyCode === 9 && !e.shiftKey) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              var nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ? getMenuLink(linkIndex, thisSubMenuLinks, 'next') : getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');
              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || e.shiftKey && e.keyCode === 9) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              var prevMenu = allLinksArray[subMenuIndex - 1];
              var prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ? getMenuLink(linkIndex, thisSubMenuLinks, 'prev') : getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };
  megaMenus.forEach(function(menu) {
    var clearActiveListItems = function clearActiveListItems() {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(function(menuItem) {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    var setMenuActive = function setMenuActive(element) {
      var active = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var onCloseFocusElement = arguments.length > 2 ? arguments[2] : undefined;
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        var mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        var headerEl = menu.parentNode.parentNode;
        var topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        var searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        var mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', function() {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });
        if (searchBtn) {
          searchBtn.addEventListener('click', function() {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(function(menuBtn) {
          var handleSubMenus = function handleSubMenus() {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            var targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        var collapseMenus = menu.querySelectorAll('.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle');
        collapseMenus.forEach(function(collapseToggle) {
          var handleThirdLevelMenus = function handleThirdLevelMenus() {
            var panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = "".concat(panel.scrollHeight, "px");
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);
    var topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    var menuDelay = false;
    var enterTimeOut;
    var leaveTimeOut;
    var delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach(function(topLevelLink, topLevelLinkIndex) {
      // return list item parent of the current link if it exists else return the link
      var topLevelListItem = topLevelLink.parentNode.tagName === 'LI' || topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ? topLevelLink.parentNode : topLevelLink;
      var subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      var hasSubmenuChildren = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(function(subMenu) {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }
      var openSubMenu = function openSubMenu(e) {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };
      var handleKeydown = function handleKeydown(e, key) {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          var prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          var nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      var isTopLevelWithMenu = topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length;
      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', function() {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            enterTimeOut = setTimeout(function() {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem.querySelector('.wmnds-mega-menu__container').addEventListener('mouseover', function() {
          if (menuDelay) {
            // if container is rehovered before timeout is done, clear all timeouts kill the delay
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            menuDelay = false;
          }
        });
        topLevelListItem.addEventListener('mouseleave', function() {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(function() {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });
        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }
      topLevelListItem.addEventListener('keydown', function(e) {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', function(e) {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', function(e) {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      var subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');
      if (subMenuContainer) {
        setKeyboardNavigation(subMenuContainer, '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          function() {
            return topLevelLink.focus();
          },
          // what to do on last link
          function() {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          });
      }
    });

    // set up keyboard navigation for search menu links
    var searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(searchMenuContainer, '.wmnds-search-list',
        // what to do on first link
        function() {
          return menu.querySelector('.wmnds-search-bar__input').focus();
        },
        // what to do on last link
        function() {
          return setMenuActive(menu.querySelector('.wmnds-mega-menu__search'), false, menu.querySelector('.wmnds-mega-menu__search-btn'));
        });
    }
  });
};
var _default = headerJs;
exports["default"] = _default;

Recommended javascript (ES6)
const headerJs = () => {
  // get mega menu elements
  const megaMenus = document.querySelectorAll('.wmnds-mega-menu');

  const mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  const getMenuLink = (currentIndex, array, direction) => {
    let menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  const setKeyboardNavigation = (subMenuContainer, subMenuQuery, onFirst, onLast) => {
    // array of all links in menu container
    const allLinksArray = [];

    // use specified query to select all submenus
    const subMenus = subMenuContainer.querySelectorAll(subMenuQuery);

    subMenus.forEach((subMenu, subMenuIndex) => {
      const thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach((link, linkIndex) => {
        link.addEventListener('keydown', e => {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              const nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              const prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              const nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ?
                getMenuLink(linkIndex, thisSubMenuLinks, 'next') :
                getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');

              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || (e.shiftKey && e.keyCode === 9)) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              const prevMenu = allLinksArray[subMenuIndex - 1];
              let prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ?
                  getMenuLink(linkIndex, thisSubMenuLinks, 'prev') :
                  getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };

  megaMenus.forEach(menu => {
    const clearActiveListItems = () => {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(menuItem => {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    const setMenuActive = (element, active = true, onCloseFocusElement) => {
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        const mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        const headerEl = menu.parentNode.parentNode;

        const topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        const searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        const mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', () => {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove(
              'wmnds-header--mega-menu-open',
              'wmnds-header--mega-menu-submenu-open'
            );
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });

        if (searchBtn) {
          searchBtn.addEventListener('click', () => {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove(
                'wmnds-header--mega-menu-open',
                'wmnds-header--mega-menu-submenu-open'
              );
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(menuBtn => {
          const handleSubMenus = () => {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            const targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        const collapseMenus = menu.querySelectorAll(
          '.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle'
        );
        collapseMenus.forEach(collapseToggle => {
          const handleThirdLevelMenus = () => {
            const panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = `${panel.scrollHeight}px`;
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);

    const topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    let menuDelay = false;
    let enterTimeOut;
    let leaveTimeOut;
    const delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach((topLevelLink, topLevelLinkIndex) => {
      // return list item parent of the current link if it exists else return the link
      const topLevelListItem =
        topLevelLink.parentNode.tagName === 'LI' ||
        topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ?
        topLevelLink.parentNode :
        topLevelLink;

      const subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      const hasSubmenuChildren =
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(subMenu => {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }

      const openSubMenu = e => {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };

      const handleKeydown = (e, key) => {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          const prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          const nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      const isTopLevelWithMenu = topLevelListItem.querySelectorAll(
        '.wmnds-mega-menu__container'
      ).length;

      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', () => {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);

            enterTimeOut = setTimeout(() => {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem
          .querySelector('.wmnds-mega-menu__container')
          .addEventListener('mouseover', () => {
            if (menuDelay) {
              // if container is rehovered before timeout is done, clear all timeouts kill the delay
              clearTimeout(enterTimeOut);
              clearTimeout(leaveTimeOut);
              menuDelay = false;
            }
          });
        topLevelListItem.addEventListener('mouseleave', () => {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(() => {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });

        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }

      topLevelListItem.addEventListener('keydown', e => {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', e => {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', e => {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      const subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');

      if (subMenuContainer) {
        setKeyboardNavigation(
          subMenuContainer,
          '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          () => topLevelLink.focus(),
          // what to do on last link
          () => {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          }
        );
      }
    });

    // set up keyboard navigation for search menu links
    const searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(
        searchMenuContainer,
        '.wmnds-search-list',
        // what to do on first link
        () => menu.querySelector('.wmnds-search-bar__input').focus(),
        // what to do on last link
        () =>
        setMenuActive(
          menu.querySelector('.wmnds-mega-menu__search'),
          false,
          menu.querySelector('.wmnds-mega-menu__search-btn')
        )
      );
    }
  });
};

export default headerJs;

With a title variant of header

When developing a service you may not need the navigation of the main website. When this is the case, you can place the title of the service in the header (providing their is no other h1 element on the page).

To use the title variant:

  • Add the h1 element and ensure it has the classes .wmnds-header__title .wmnds-col-1 .wmnds-col-sm-auto on the element


HTML markup
<!-- Skip to content link -->
<a href="#wmnds-main-content" title="Skip to main content" target="_self" class="wmnds-link wmnds-header__skip-link">
  Skip to main content
</a>
<!-- Main header section -->
<header>
  <div class="wmnds-bg-white wmnds-p-t-md wmnds-p-b-md wmnds-cookies-banner">
    <div class="wmnds-container">
      <div class="wmnds-col-1 wmnds-col-md-3-4 wmnds-col-lg-2-3">
        <h3>Your privacy settings</h3>
        <p>
          We use cookies to help you with journey planning and relevant disruptions, remember your login and show you
          content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority
          and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.
        </p>
        <div class="wmnds-grid wmnds-grid--justify-between wmnds-cookies-banner__group-buttons">
          <button class="wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24  wmnds-cookies-banner__accept-all-cookies wmnds-text-align-center" type="button">
            Accept all cookies
          </button>
          <a href="https://www.tfwm.org.uk/manage-cookies/" title="link title" target="_self" class="wmnds-btn wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24 wmnds-text-align-center">
            Manage Cookies
          </a>
        </div>
      </div>
    </div>
  </div>
  <div class="wmnds-header">
    <div class="wmnds-container wmnds-grid wmnds-grid--align-center wmnds-grid--justify-between">
      <div class="wmnds-header__vertical-align wmnds-col-auto">
        <!-- Logo -->
        <a class="wmnds-header__logo-link" href="/" title="Transport for West Midlands Design System">
          <img class="wmnds-header__logo" alt="Transport for West Midlands logo" src="/img/logo.svg" />
        </a>
      </div>
      <!-- Header title -->
      <h1 class="wmnds-header__title wmnds-col-1 wmnds-col-sm-auto">
        Reinstate your Direct Debit<br>(COVID-19)
      </h1>
    </div>
  </div>
</header>

Recommended javascript (browser compatible)
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var headerJs = function headerJs() {
  // get mega menu elements
  var megaMenus = document.querySelectorAll('.wmnds-mega-menu');
  var mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  var getMenuLink = function getMenuLink(currentIndex, array, direction) {
    var menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  var setKeyboardNavigation = function setKeyboardNavigation(subMenuContainer, subMenuQuery, onFirst, onLast) {
    // array of all links in menu container
    var allLinksArray = [];

    // use specified query to select all submenus
    var subMenus = subMenuContainer.querySelectorAll(subMenuQuery);
    subMenus.forEach(function(subMenu, subMenuIndex) {
      var thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach(function(link, linkIndex) {
        link.addEventListener('keydown', function(e) {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              var nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              var prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || e.keyCode === 9 && !e.shiftKey) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              var nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ? getMenuLink(linkIndex, thisSubMenuLinks, 'next') : getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');
              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || e.shiftKey && e.keyCode === 9) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              var prevMenu = allLinksArray[subMenuIndex - 1];
              var prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ? getMenuLink(linkIndex, thisSubMenuLinks, 'prev') : getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };
  megaMenus.forEach(function(menu) {
    var clearActiveListItems = function clearActiveListItems() {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(function(menuItem) {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    var setMenuActive = function setMenuActive(element) {
      var active = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var onCloseFocusElement = arguments.length > 2 ? arguments[2] : undefined;
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        var mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        var headerEl = menu.parentNode.parentNode;
        var topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        var searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        var mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', function() {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });
        if (searchBtn) {
          searchBtn.addEventListener('click', function() {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove('wmnds-header--mega-menu-open', 'wmnds-header--mega-menu-submenu-open');
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(function(menuBtn) {
          var handleSubMenus = function handleSubMenus() {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            var targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        var collapseMenus = menu.querySelectorAll('.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle');
        collapseMenus.forEach(function(collapseToggle) {
          var handleThirdLevelMenus = function handleThirdLevelMenus() {
            var panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = "".concat(panel.scrollHeight, "px");
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);
    var topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    var menuDelay = false;
    var enterTimeOut;
    var leaveTimeOut;
    var delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach(function(topLevelLink, topLevelLinkIndex) {
      // return list item parent of the current link if it exists else return the link
      var topLevelListItem = topLevelLink.parentNode.tagName === 'LI' || topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ? topLevelLink.parentNode : topLevelLink;
      var subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      var hasSubmenuChildren = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(function(subMenu) {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }
      var openSubMenu = function openSubMenu(e) {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };
      var handleKeydown = function handleKeydown(e, key) {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          var prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          var nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      var isTopLevelWithMenu = topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length;
      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', function() {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            enterTimeOut = setTimeout(function() {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem.querySelector('.wmnds-mega-menu__container').addEventListener('mouseover', function() {
          if (menuDelay) {
            // if container is rehovered before timeout is done, clear all timeouts kill the delay
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);
            menuDelay = false;
          }
        });
        topLevelListItem.addEventListener('mouseleave', function() {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(function() {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });
        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }
      topLevelListItem.addEventListener('keydown', function(e) {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', function(e) {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', function(e) {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      var subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');
      if (subMenuContainer) {
        setKeyboardNavigation(subMenuContainer, '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          function() {
            return topLevelLink.focus();
          },
          // what to do on last link
          function() {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          });
      }
    });

    // set up keyboard navigation for search menu links
    var searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(searchMenuContainer, '.wmnds-search-list',
        // what to do on first link
        function() {
          return menu.querySelector('.wmnds-search-bar__input').focus();
        },
        // what to do on last link
        function() {
          return setMenuActive(menu.querySelector('.wmnds-mega-menu__search'), false, menu.querySelector('.wmnds-mega-menu__search-btn'));
        });
    }
  });
};
var _default = headerJs;
exports["default"] = _default;

Recommended javascript (ES6)
const headerJs = () => {
  // get mega menu elements
  const megaMenus = document.querySelectorAll('.wmnds-mega-menu');

  const mobileMenu = window.matchMedia('(max-width: 767px)');

  /*
      Mega menu helper functions
  */

  // getMenuLink returns a specified menu link from a specified array
  // currentIndex = index of the link that is currently focused
  // array = array to move through
  // direction = next, prev,
  const getMenuLink = (currentIndex, array, direction) => {
    let menuLink = null;
    if (array) {
      if (direction === 'prev') {
        // return previous link in specified array if there is one else return null;
        menuLink = array[currentIndex - 1] ? array[currentIndex - 1] : null;
      } else if (direction === 'next') {
        // return next link in specified array if there is one else return null;
        menuLink = array[currentIndex + 1] ? array[currentIndex + 1] : null;
      } else {
        // return link with same index in specified array;
        menuLink = array[currentIndex] ? array[currentIndex] : array[array.length - 1];
      }
    }
    return menuLink;
  };

  // takes a menu element and allows moving between focus via tabbing/arrows
  const setKeyboardNavigation = (subMenuContainer, subMenuQuery, onFirst, onLast) => {
    // array of all links in menu container
    const allLinksArray = [];

    // use specified query to select all submenus
    const subMenus = subMenuContainer.querySelectorAll(subMenuQuery);

    subMenus.forEach((subMenu, subMenuIndex) => {
      const thisSubMenuLinks = subMenu.querySelectorAll('a');

      // add list of all links in this container to an array
      allLinksArray.push(thisSubMenuLinks);

      // add event listener to each link with key logic
      thisSubMenuLinks.forEach((link, linkIndex) => {
        link.addEventListener('keydown', e => {
          // if not escape
          if (e.keyCode !== 27) {
            e.stopPropagation();
            if (e.keyCode === 39) {
              // right arrow - go to link of same index in next menu list
              e.preventDefault();
              const nextMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex + 1]);
              if (nextMenuLink) nextMenuLink.focus();
            } else if (e.keyCode === 37) {
              // left arrow - go to link of same index in previous menu list
              e.preventDefault();
              const prevMenuLink = getMenuLink(linkIndex, allLinksArray[subMenuIndex - 1]);
              if (prevMenuLink) prevMenuLink.focus();
            } else if (e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) {
              // down arrow or tab - go to next link in current menu list
              e.preventDefault();
              // if next link doesn't exist try next menu first item else return null
              const nextLink = getMenuLink(linkIndex, thisSubMenuLinks, 'next') ?
                getMenuLink(linkIndex, thisSubMenuLinks, 'next') :
                getMenuLink(-1, allLinksArray[subMenuIndex + 1], 'next');

              if (nextLink) {
                nextLink.focus();
              } else if (onLast) {
                onLast();
              }
            } else if (e.keyCode === 38 || (e.shiftKey && e.keyCode === 9)) {
              // up arrow or shift + tab - go to previous item in current menu list
              e.preventDefault();
              const prevMenu = allLinksArray[subMenuIndex - 1];
              let prevLink = null;
              if (prevMenu || linkIndex > 0) {
                prevLink = getMenuLink(linkIndex, thisSubMenuLinks, 'prev') ?
                  getMenuLink(linkIndex, thisSubMenuLinks, 'prev') :
                  getMenuLink(prevMenu.length, prevMenu, 'prev');
              }
              if (prevLink) {
                prevLink.focus();
              } else if (onFirst) {
                onFirst();
              }
            }
          }
        });
      });
    });
  };

  megaMenus.forEach(menu => {
    const clearActiveListItems = () => {
      // remove active classes from other list items
      menu.querySelectorAll('.wmnds-mega-menu__primary-menu-item').forEach(menuItem => {
        menuItem.classList.remove('active');
      });
    };

    // handle setting the active class on menu and list items
    const setMenuActive = (element, active = true, onCloseFocusElement) => {
      if (active) {
        menu.classList.add('active');
        clearActiveListItems();
        // add active class to current item
        element.classList.add('active');
      } else {
        menu.classList.remove('active');
        element.classList.remove('active');
        // set focus on menu close

        if (onCloseFocusElement) onCloseFocusElement.focus();
      }
    };

    // mobile nav function
    function handleMobileMenu(mq) {
      if (mq.matches) {
        const mobileToggle = menu.querySelector('.wmnds-mega-menu__mobile-toggle');
        const headerEl = menu.parentNode.parentNode;

        const topLevelMenuBtn = menu.querySelectorAll('.wmnds-mega-menu__link-arrow-icon-btn');
        const searchBtn = menu.querySelector('.wmnds-mega-menu__search-btn');
        // object to see which menu/menu level is open
        const mobileMenuIsOpen = {
          menu: false,
          primary: false,
          search: false
        };

        // handle mobile menu toggle
        mobileToggle.addEventListener('click', () => {
          mobileMenuIsOpen.menu = !mobileMenuIsOpen.menu;
          if (mobileMenuIsOpen.menu) {
            mobileMenuIsOpen.search = false;
            headerEl.classList.remove('wmnds-header--search-open');
            headerEl.classList.add('wmnds-header--mega-menu-open');
            document.querySelector('html').classList.add('mobile-menu-open');
          } else {
            headerEl.classList.remove(
              'wmnds-header--mega-menu-open',
              'wmnds-header--mega-menu-submenu-open'
            );
            document.querySelector('html').classList.remove('mobile-menu-open');
          }
        });

        if (searchBtn) {
          searchBtn.addEventListener('click', () => {
            mobileMenuIsOpen.search = !mobileMenuIsOpen.search;
            if (mobileMenuIsOpen.search) {
              mobileMenuIsOpen.menu = false;
              headerEl.classList.remove(
                'wmnds-header--mega-menu-open',
                'wmnds-header--mega-menu-submenu-open'
              );
              document.querySelector('html').classList.remove('mobile-menu-open');
              headerEl.classList.add('wmnds-header--search-open');
            } else {
              headerEl.classList.remove('wmnds-header--search-open');
            }
          });
        }

        // handle sub menu open/close
        topLevelMenuBtn.forEach(menuBtn => {
          const handleSubMenus = () => {
            mobileMenuIsOpen.primary = !mobileMenuIsOpen.primary;
            const targetListItem = menuBtn.parentNode;
            if (mobileMenuIsOpen.primary) {
              targetListItem.classList.add('open');
              targetListItem.querySelector('.wmnds-mega-menu__sub-menu-link').focus();
              headerEl.classList.add('wmnds-header--mega-menu-submenu-open');
            } else {
              targetListItem.classList.remove('open');
              headerEl.classList.remove('wmnds-header--mega-menu-submenu-open');
            }
          };
          menuBtn.previousElementSibling.addEventListener('click', handleSubMenus);
          menuBtn.addEventListener('click', handleSubMenus);
        });

        // mobile collapse for third level menus
        const collapseMenus = menu.querySelectorAll(
          '.wmnds-mega-menu__sub-menu-item .wmnds-mega-menu__collapse-toggle'
        );
        collapseMenus.forEach(collapseToggle => {
          const handleThirdLevelMenus = () => {
            const panel = collapseToggle.nextElementSibling;
            collapseToggle.classList.toggle('open');
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = `${panel.scrollHeight}px`;
            }
          };
          if (collapseToggle.previousElementSibling.tagName !== 'A') {
            collapseToggle.previousElementSibling.addEventListener('click', handleThirdLevelMenus);
          }
          collapseToggle.addEventListener('click', handleThirdLevelMenus);
        });
      }
    }
    // end mobile nav function

    // init mobile nav function
    handleMobileMenu(mobileMenu);
    mobileMenu.addListener(handleMobileMenu);

    const topLevelLinks = menu.querySelectorAll('.wmnds-mega-menu__primary-menu-link');
    let menuDelay = false;
    let enterTimeOut;
    let leaveTimeOut;
    const delayTime = 300;

    // handle events within each top level list item
    topLevelLinks.forEach((topLevelLink, topLevelLinkIndex) => {
      // return list item parent of the current link if it exists else return the link
      const topLevelListItem =
        topLevelLink.parentNode.tagName === 'LI' ||
        topLevelLink.parentNode.className.includes('wmnds-mega-menu__search') ?
        topLevelLink.parentNode :
        topLevelLink;

      const subMenuLinks = topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-link');

      // check if level 3 menus are present, if so add modifier class
      const hasSubmenuChildren =
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu-child-menu').length !== 0;
      if (hasSubmenuChildren) {
        topLevelListItem.querySelectorAll('.wmnds-mega-menu__sub-menu').forEach(subMenu => {
          subMenu.classList.add('wmnds-mega-menu__sub-menu--has-child-menus');
        });
      }

      const openSubMenu = e => {
        // check if list item has a mega menu
        if (topLevelListItem.querySelectorAll('.wmnds-mega-menu__container').length) {
          e.preventDefault();
          // remove keyFocus to allow menu to show
          setMenuActive(topLevelListItem, true);
          // focus first menu item
          if (topLevelListItem.contains(subMenuLinks[0])) {
            subMenuLinks[0].focus();
          } else if (topLevelListItem.querySelector('.wmnds-search-bar__input')) {
            topLevelListItem.querySelector('.wmnds-search-bar__input').focus();
          }
        }
      };

      const handleKeydown = (e, key) => {
        e.stopPropagation();
        // if key pressed is enter, space bar or down arrow
        if (key === 13 || key === 32 || key === 40) {
          // enter
          // check if link exists
          if (key === 13) {
            if (!topLevelLink.tagName === 'a' || !topLevelLink.getAttribute('href')) {
              openSubMenu(e);
            }
          } else {
            openSubMenu(e);
          }
        } else if (key === 37) {
          // left arrow
          const prevLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'prev');
          if (prevLink) prevLink.focus();
        } else if (key === 39) {
          // right arrow
          const nextLink = getMenuLink(topLevelLinkIndex, topLevelLinks, 'next');
          if (nextLink) nextLink.focus();
        } else if (key === 27) {
          // if escape pressed
          setMenuActive(topLevelListItem, false, topLevelLink);
        }
      };

      // if top level link doesn't have a mega-menu child add class to menu to hide overlay when hovered
      // has to be added/removed on mouseover to cover menus that have a mix of items with/without mega menus
      const isTopLevelWithMenu = topLevelListItem.querySelectorAll(
        '.wmnds-mega-menu__container'
      ).length;

      if (isTopLevelWithMenu) {
        topLevelLink.addEventListener('mouseover', () => {
          if (!menuDelay) {
            // if no menuDelay is active just open the menu
            setMenuActive(topLevelListItem);
          } else {
            // if menuDelay is active, clear all timeouts and start a new one
            clearTimeout(enterTimeOut);
            clearTimeout(leaveTimeOut);

            enterTimeOut = setTimeout(() => {
              // enter timeout completed, open menu and kill delay
              menuDelay = false;
              setMenuActive(topLevelListItem);
            }, delayTime);
          }
        });
        topLevelListItem
          .querySelector('.wmnds-mega-menu__container')
          .addEventListener('mouseover', () => {
            if (menuDelay) {
              // if container is rehovered before timeout is done, clear all timeouts kill the delay
              clearTimeout(enterTimeOut);
              clearTimeout(leaveTimeOut);
              menuDelay = false;
            }
          });
        topLevelListItem.addEventListener('mouseleave', () => {
          menuDelay = true;
          // leave timeout is active
          leaveTimeOut = setTimeout(() => {
            // leave timeout completed, close menu
            setMenuActive(topLevelListItem, false);
            menuDelay = false;
          }, delayTime);
        });

        topLevelListItem.addEventListener('blur', setMenuActive(topLevelListItem, false));
      }

      topLevelListItem.addEventListener('keydown', e => {
        handleKeydown(e, e.keyCode);
      });

      // top lvl link event listeners
      topLevelLink.addEventListener('focus', e => {
        e.preventDefault();
        setMenuActive(topLevelListItem, false);
        clearActiveListItems();
      });
      topLevelLink.addEventListener('mousedown', e => {
        // prevent link focus on click
        e.preventDefault();
      });

      // set up keyboard navigation for sub menu links
      const subMenuContainer = topLevelListItem.querySelector('.wmnds-mega-menu__sub-menu');

      if (subMenuContainer) {
        setKeyboardNavigation(
          subMenuContainer,
          '.wmnds-mega-menu__sub-menu-item',
          // what to do on first link
          () => topLevelLink.focus(),
          // what to do on last link
          () => {
            setMenuActive(topLevelListItem, false);
            if (getMenuLink(topLevelLinkIndex, topLevelLinks, 'next')) {
              getMenuLink(topLevelLinkIndex, topLevelLinks, 'next').focus();
            }
          }
        );
      }
    });

    // set up keyboard navigation for search menu links
    const searchMenuContainer = menu.querySelector('.wmnds-search-container');
    if (searchMenuContainer) {
      setKeyboardNavigation(
        searchMenuContainer,
        '.wmnds-search-list',
        // what to do on first link
        () => menu.querySelector('.wmnds-search-bar__input').focus(),
        // what to do on last link
        () =>
        setMenuActive(
          menu.querySelector('.wmnds-mega-menu__search'),
          false,
          menu.querySelector('.wmnds-mega-menu__search-btn')
        )
      );
    }
  });
};

export default headerJs;

Archived header

This is an old version fo the header pattern for reference only. Use the current version instead.


Skip to main content

Your privacy settings

We use cookies to help you with journey planning and relevant disruptions, remember your login and show you content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.

Manage Cookies
Beta

This is a new service - your feedback will help us to improve it.


HTML markup
<!-- Skip to content link -->
<a href="#wmnds-main-content" title="Skip to main content" target="_self" class="wmnds-link wmnds-header__skip-link">
  Skip to main content
</a>
<!-- Main header section -->
<header>
  <div class="wmnds-bg-white wmnds-p-t-md wmnds-p-b-md wmnds-cookies-banner">
    <div class="wmnds-container">
      <div class="wmnds-col-1 wmnds-col-md-3-4 wmnds-col-lg-2-3">
        <h3>Your privacy settings</h3>
        <p>
          We use cookies to help you with journey planning and relevant disruptions, remember your login and show you
          content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority
          and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.
        </p>
        <div class="wmnds-grid wmnds-grid--justify-between wmnds-cookies-banner__group-buttons">
          <button class="wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24  wmnds-cookies-banner__accept-all-cookies wmnds-text-align-center" type="button">
            Accept all cookies
          </button>
          <a href="https://www.tfwm.org.uk/manage-cookies/" title="link title" target="_self" class="wmnds-btn wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24 wmnds-text-align-center">
            Manage Cookies
          </a>
        </div>
      </div>
    </div>
  </div>
  <div class="wmnds-header">
    <div class="wmnds-container wmnds-grid wmnds-grid--align-center wmnds-grid--justify-between">
      <div class="wmnds-header__vertical-align wmnds-col-auto">
        <!-- Logo -->
        <a class="wmnds-header__logo-link" href="/" title="Transport for West Midlands Design System">
          <img class="wmnds-header__logo" alt="Transport for West Midlands logo" src="/img/logo.svg" />
        </a>
      </div>
      <!-- Nav items -->
      <nav class="wmnds-header__vertical-align wmnds-col-auto" aria-label="Full header example navigation">
        <ul class="wmnds-header__links wmnds-header__main-links">
          <li class="wmnds-header__link">
            <a href="/docs/" title="Docs page" target="_self" class="wmnds-link">
              Docs
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/styles/" title="Styles page" target="_self" class="wmnds-link">
              Styles
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/components/" title="Components page" target="_self" class="wmnds-link">
              Components
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/patterns/" title="Patterns page" target="_self" class="wmnds-link">
              Patterns
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/user-research/" title="User research page" target="_self" class="wmnds-link">
              User research
            </a>
          </li>
        </ul>
      </nav>
    </div>
  </div>
  <div class="wmnds-container">
    <!-- Phase banner -->
    <div class="wmnds-banner-container">
      <div class="wmnds-col-1">
        <div class="wmnds-banner-container__phase-wrapper">
          <span class="wmnds-phase-indicator">
            Beta
          </span>
        </div>
        <p class="wmnds-banner-container__text">
          This is a new service - your
          <a href="https://github.com/wmcadigital/wmn-design-system/issues" title="WMN Design System Github" target="_blank" class="wmnds-link" rel="noopener noreferrer">
            feedback
          </a>
          will help us to improve it.
        </p>
      </div>
    </div>
    <!-- Breadcrumbs -->
    <nav aria-label="Breadcrumbs" class="wmnds-breadcrumb">
      <ol class="wmnds-breadcrumb__list">
        <li class="wmnds-breadcrumb__list-item">
          <a href="/" class="wmnds-breadcrumb__link">
            Home
          </a>
        </li>
        <li class="wmnds-breadcrumb__list-item">
          <a href="/patterns" class="wmnds-breadcrumb__link">
            Patterns
          </a>
        </li>
        <li class="wmnds-breadcrumb__list-item">
          <a href="/patterns/header" class="wmnds-breadcrumb__link wmnds-breadcrumb__link--current" aria-current="page">
            Header
          </a>
        </li>
      </ol>
    </nav>
  </div>
</header>

Mobile app variant of header

When developing a mobile app, if you are limited for space and need extra room then it is recommended to use the mobile app variant of the Transport for West Midlands header.

To use the mobile app variant:

  • Add the modifier class wmnds-header--mobile-app to the wmnds-header element
  • Copy the code for the back button section below and insert it into your existing header
  • Finally, add the script for the back button in your local javascript file

You will most likely want to use this with the mobile variants of the breadcrumb component and footer pattern .


Skip to main content

Your privacy settings

We use cookies to help you with journey planning and relevant disruptions, remember your login and show you content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.

Manage Cookies

HTML markup
<!-- Skip to content link -->
<a href="#wmnds-main-content" title="Skip to main content" target="_self" class="wmnds-link wmnds-header__skip-link">
  Skip to main content
</a>
<!-- Main header section -->
<header>
  <div class="wmnds-bg-white wmnds-p-t-md wmnds-p-b-md wmnds-cookies-banner">
    <div class="wmnds-container">
      <div class="wmnds-col-1 wmnds-col-md-3-4 wmnds-col-lg-2-3">
        <h3>Your privacy settings</h3>
        <p>
          We use cookies to help you with journey planning and relevant disruptions, remember your login and show you
          content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority
          and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.
        </p>
        <div class="wmnds-grid wmnds-grid--justify-between wmnds-cookies-banner__group-buttons">
          <button class="wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24  wmnds-cookies-banner__accept-all-cookies wmnds-text-align-center" type="button">
            Accept all cookies
          </button>
          <a href="https://www.tfwm.org.uk/manage-cookies/" title="link title" target="_self" class="wmnds-btn wmnds-btn wmnds-col-1 wmnds-col-sm-1 wmnds-col-md-12-24 wmnds-text-align-center">
            Manage Cookies
          </a>
        </div>
      </div>
    </div>
  </div>
  <div class="wmnds-header wmnds-header--mobile-app">
    <div class="wmnds-container wmnds-grid wmnds-grid--align-center wmnds-grid--justify-between">
      <div class="wmnds-header__vertical-align wmnds-col-auto">
        <!-- Logo -->
        <a class="wmnds-header__logo-link" href="/" title="Transport for West Midlands Design System">
          <img class="wmnds-header__logo" alt="Transport for West Midlands logo" src="/img/logo.svg" />
        </a>
      </div>
      <!-- Nav items -->
      <nav class="wmnds-header__vertical-align wmnds-col-auto" aria-label="Mobile app header example navigation">
        <ul class="wmnds-header__links wmnds-header__main-links">
          <li class="wmnds-header__link">
            <a href="/docs/" title="Docs page" target="_self" class="wmnds-link">
              Docs
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/styles/" title="Styles page" target="_self" class="wmnds-link">
              Styles
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/components/" title="Components page" target="_self" class="wmnds-link">
              Components
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/patterns/" title="Patterns page" target="_self" class="wmnds-link">
              Patterns
            </a>
          </li>
          <li class="wmnds-header__link">
            <a href="/user-research/" title="User research page" target="_self" class="wmnds-link">
              User research
            </a>
          </li>
        </ul>
        <!-- Back button -->
        <ul class="wmnds-header__links wmnds-header__back-btn">
          <li class="wmnds-header__link">
            <a href="#" title="Go back to previous page" target="_self" class="wmnds-link" onClick="goBack(event);">
              Back
            </a>
          </li>
        </ul>
        <script>
          // Function that sends user to previous page they were on,
          // This can be included in your local javascript file
          function goBack(e) {
            e.preventDefault();
            window.history.back();
          }

        </script>
        <!-- End back button -->
      </nav>
    </div>
  </div>
</header>