An expandable menu used in the Navigation component, consisting of Menu Items and an optional Card component.

Usage

Import using Webpack as an ES module:

import MzpMenu from '@mozilla-protocol/core/protocol/js/menu';

Import using Webpack as CommonJS:

const MzpMenu = require('@mozilla-protocol/core/protocol/js/menu');

Import as a global variable via a <script> tag:

const MzpMenu = window.MzpMenu;

You can then initialize the component using init().

MzpMenu.init();

You can also pass custom callbacks for menu open and close events as a configuration object like so:

MzpMenu.init({
  onMenuOpen: function () {
    console.log('Menu opened');
  },
  onMenuClose: function () {
    console.log('Menu closed');
  },
  onMenuButtonClose: function () {
    console.log(
      'Menu close button clicked');
  }
})

Tips

  • Make sure to initialize the component after the DOM has loaded.
  • On wide viewports a menu’s content is displayed when hovering or focusing on a menu link.
  • On small viewports a menu’s content is expanded/collapsed when clicking on a menu link.
  • Menu content should consist of two lists of one or more Menu Items.
  • A Small Card can also be included inside a menu using the mzp-has-card class. Cards are only visible on wide viewports.
  • A menu can also feature regular links that do not expand on hover/click by omitting the mzp-has-drop-down and mzp-js-expandable classes.
  • A menu with a state class of mzp-is-basic is accessible without JavaScript. This state class gets replaced with mzp-is-enhanced when JS is executed.
<nav class="mzp-c-menu mzp-is-basic">
  <ul class="mzp-c-menu-category-list">
    <li class="mzp-c-menu-category">
      <a class="mzp-c-menu-heading" href="https://www.mozilla.org/">Sample Link</a>
    </li>
    <li class="mzp-c-menu-category mzp-has-drop-down mzp-js-expandable">
      <a class="mzp-c-menu-heading" href="#" aria-haspopup="true"
        aria-controls="mzp-c-menu-panel-example">Sample Link with Popup</a>
      <div class="mzp-c-menu-panel mzp-has-card" id="mzp-c-menu-panel-example">
        <div class="mzp-c-menu-panel-container">
          <button
            class="mzp-c-menu-button-close"
            type="button"
            aria-controls="mzp-c-menu-panel-example"
          >
            Close menu
          </button>
          <div class="mzp-c-menu-panel-content">
            <ul>
              <li>
                
<section class="mzp-c-menu-item  mzp-has-icon">
  <div class="mzp-c-menu-item-head">
    <img class="mzp-c-menu-item-icon" src="/protocol/img/icons/image.svg" alt="Useful alt text where appropriate">
    <h4 class="mzp-c-menu-item-heading">A headline with 30 characters</h4>
    
    <p class="mzp-c-menu-item-body">This is a short description with only a single sentence and no more.</p>
    
  </div>
  
  <ul class="mzp-c-menu-item-list">
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
  </ul>
  
</section>

              </li>
              <li>
                
<section class="mzp-c-menu-item  mzp-has-icon">
  <div class="mzp-c-menu-item-head">
    <img class="mzp-c-menu-item-icon" src="/protocol/img/icons/image.svg" alt="Useful alt text where appropriate">
    <h4 class="mzp-c-menu-item-heading">A headline with 30 characters</h4>
    
    <p class="mzp-c-menu-item-body">This is a short description with only a single sentence and no more.</p>
    
  </div>
  
  <ul class="mzp-c-menu-item-list">
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
    <li>
      <a href="#">Secondary link</a>
    </li>
    
  </ul>
  
</section>

              </li>
            </ul>
            <ul>
              <li>
                
<section class="mzp-c-menu-item  ">
  <div class="mzp-c-menu-item-head">
    
    <h4 class="mzp-c-menu-item-heading">A headline with 30 characters</h4>
    
    <p class="mzp-c-menu-item-body">This is a short description with only a single sentence and no more.</p>
    
  </div>
  
</section>

              </li>
              <li>
                
<section class="mzp-c-menu-item  ">
  <div class="mzp-c-menu-item-head">
    
    <h4 class="mzp-c-menu-item-heading">A headline with 30 characters</h4>
    
    <p class="mzp-c-menu-item-body">This is a short description with only a single sentence and no more.</p>
    
  </div>
  
</section>

              </li>
              <li>
                
<section class="mzp-c-menu-item  ">
  <div class="mzp-c-menu-item-head">
    
    <h4 class="mzp-c-menu-item-heading">A headline with 30 characters</h4>
    
    <p class="mzp-c-menu-item-body">This is a short description with only a single sentence and no more.</p>
    
  </div>
  
</section>

              </li>
            </ul>
          </div>
          <div class="mzp-c-menu-panel-card">
            
<section class="mzp-c-card mzp-c-card-small mzp-has-aspect-3-2">
  <a class="mzp-c-card-block-link" href="#">
    <div class="mzp-c-card-media-wrapper">
      <img class="mzp-c-card-image" src="../../img/image-3-2.jpg" alt="">
    </div>
    <div class="mzp-c-card-content">
      
      <h2 class="mzp-c-card-heading">A short heading</h2>
      <p class="mzp-c-card-body">This is an optional card included in the menu. Only visible on wide viewports.</p>
      
      
    </div>
  </a>
</section>

          </div>
        </div>
      </div>
    </li>
  </ul>
</nav>

<script src="../../protocol/js/menu.js"></script>

<script>
  window.MzpMenu.init({
    onMenuOpen: function () {
      console.log('Menu opened');
    },
    onMenuClose: function () {
      console.log('Menu closed');
    },
    onMenuButtonClose: function () {
      console.log(
        'Menu close button clicked');
    }
  });
</script>