<nav class="n7-primary-navigation flex lg:justify-end" aria-label="Principale" id="siteNavWrapper">
    <button type="button" class="n7-btn 
    n7-btn--only-text rounded-0 lg:hidden ml-auto n7-btn--icon group" aria-expanded="false" aria-controls="mainNavPanel" id="mobileNavToggle">
        <svg class="inline-block align-middle fill-current w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6 m-0 p-0 transition-all duration-200 ease-out transform group-hover:translate-none is-show-menu group-aria-expanded:hidden" aria-hidden="true" focusable="false" role="img">
            <use xlink:href="../../icons.svg#mini--bars-3" />
        </svg>

        <svg class="inline-block align-middle fill-current w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6 m-0 p-0 transition-all duration-200 ease-out transform group-hover:translate-none is-close-menu hidden group-aria-expanded:inline-block" aria-hidden="true" focusable="false" role="img">
            <use xlink:href="../../icons.svg#mini--x-mark" />
        </svg>

        <span class="sr-only is-show-menu group-aria-expanded:hidden">
            Menu
        </span>
        <span class="sr-only is-close-menu hidden group-aria-expanded:block">
            Chiudi menu
        </span>
    </button>
    <!-- Mobile panel -->
    <div class="n7-primary-navigation__panel flex-col bg-white transition-all invisible w-[88%] lg:w-auto fixed lg:static lg:visible top-[--header-height] bottom-0 left-[12%] lg:left-0 border-l n7-border-primary lg:border-l-0 overflow-y-auto" id="mainNavPanel">
        <!-- Main nav -->
        <div class="n7-primary-navigation__module is-main lg:border-b-0">
            <ul class="n7-primary-navigation__list lg:flex lg:justify-end gap-4 xl:gap-8 has-dropdown-menu">
                <li class="n7-dropdown-menu n7-primary-navigation__item">
                    <button class="n7-dropdown-menu__trigger dropdown-trigger group w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary aria-expanded:n7-background-gray-02 lg:aria-expanded:bg-white aria-expanded:n7-content-01" aria-expanded="false" aria-controls="submenumenu-01">
                        Menu item 1<svg class="inline-block align-middle fill-current w-5 h-5 ml-auto transition-all n7-dropdown-menu__trigger-icon group-aria-expanded:-rotate-180" aria-hidden="true" focusable="false" role="img">
                            <use xlink:href="../../icons.svg#mini--chevron-down" />
                        </svg>
                    </button>
                    <ul class="n7-dropdown-menu__list hidden lg:absolute border border-t-0 n7-border-gray-01 lg:border-t lg:rounded lg:shadow-md lg:w-52 border-r-0 border-l-0 lg:border-r lg:border-l " id="submenumenu-01">

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                voce 1
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                voce 2
                            </a>
                        </li>

                    </ul>
                </li>
                <li class="n7-dropdown-menu n7-primary-navigation__item">
                    <button class="n7-dropdown-menu__trigger dropdown-trigger group w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary aria-expanded:n7-background-gray-02 lg:aria-expanded:bg-white aria-expanded:n7-content-01" aria-expanded="false" aria-controls="submenumenu-02">
                        Menu item 2<svg class="inline-block align-middle fill-current w-5 h-5 ml-auto transition-all n7-dropdown-menu__trigger-icon group-aria-expanded:-rotate-180" aria-hidden="true" focusable="false" role="img">
                            <use xlink:href="../../icons.svg#mini--chevron-down" />
                        </svg>
                    </button>
                    <ul class="n7-dropdown-menu__list hidden lg:absolute border border-t-0 n7-border-gray-01 lg:border-t lg:rounded lg:shadow-md lg:w-52 border-r-0 border-l-0 lg:border-r lg:border-l " id="submenumenu-02">

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 1
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 3
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 4
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 5
                            </a>
                        </li>

                    </ul>
                </li>
                <li class="n7-dropdown-menu n7-primary-navigation__item">
                    <button class="n7-dropdown-menu__trigger dropdown-trigger group w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary aria-expanded:n7-background-gray-02 lg:aria-expanded:bg-white aria-expanded:n7-content-01" aria-expanded="false" aria-controls="submenumenu-03">
                        Menu item 3<svg class="inline-block align-middle fill-current w-5 h-5 ml-auto transition-all n7-dropdown-menu__trigger-icon group-aria-expanded:-rotate-180" aria-hidden="true" focusable="false" role="img">
                            <use xlink:href="../../icons.svg#mini--chevron-down" />
                        </svg>
                    </button>
                    <ul class="n7-dropdown-menu__list hidden lg:absolute border border-t-0 n7-border-gray-01 lg:border-t lg:rounded lg:shadow-md lg:w-52 border-r-0 border-l-0 lg:border-r lg:border-l " id="submenumenu-03">

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 1
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 3
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 4
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 5
                            </a>
                        </li>

                    </ul>
                </li>
                <li class="n7-dropdown-menu n7-primary-navigation__item">
                    <button class="n7-dropdown-menu__trigger dropdown-trigger group w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary aria-expanded:n7-background-gray-02 lg:aria-expanded:bg-white aria-expanded:n7-content-01" aria-expanded="false" aria-controls="submenumenu-04">
                        Menu item 4<svg class="inline-block align-middle fill-current w-5 h-5 ml-auto transition-all n7-dropdown-menu__trigger-icon group-aria-expanded:-rotate-180" aria-hidden="true" focusable="false" role="img">
                            <use xlink:href="../../icons.svg#mini--chevron-down" />
                        </svg>
                    </button>
                    <ul class="n7-dropdown-menu__list hidden lg:absolute border border-t-0 n7-border-gray-01 lg:border-t lg:rounded lg:shadow-md lg:w-52 border-r-0 border-l-0 lg:border-r lg:border-l " id="submenumenu-04">

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 1
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 3
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 4
                            </a>
                        </li>

                        <li class="n7-dropdown-menu__item group border-b n7-border-gray-01 last-of-type:border-b-0">
                            <a class="flex p-3 gap-2 items-center transition bg-white text-sm xl:text-base hover:underline hover:n7-background-gray-02 focus:n7-background-gray-02 group-first:rounded-t group-last:rounded-b" href="">
                                Item label 5
                            </a>
                        </li>

                    </ul>
                </li>
                <!-- only link item -->
                <li class="n7-primary-navigation__item">
                    <a href="" class="w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary">
                        Voce 1
                    </a>
                </li>
            </ul>
        </div>

    </div>
    <div class="n7-primary-navigation__backdrop bg-black/25 top-[--header-height] lg:hidden"></div>
</nav>
<nav class="n7-primary-navigation flex lg:justify-end" aria-label="Principale" id="siteNavWrapper">
    <button type="button" class="n7-btn 
    n7-btn--only-text rounded-0 lg:hidden ml-auto n7-btn--icon group" aria-expanded="false" aria-controls="mainNavPanel" id="mobileNavToggle">
        {% render '@icon--small', { id: 'mini--bars-3', classes: 'm-0 p-0 transition-all duration-200 ease-out transform group-hover:translate-none is-show-menu group-aria-expanded:hidden', size: 'w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6' }, true %}
        {% render '@icon--small', { id: 'mini--x-mark', classes: 'm-0 p-0 transition-all duration-200 ease-out transform group-hover:translate-none is-close-menu hidden group-aria-expanded:inline-block', size: 'w-4 h-4 md:w-5 md:h-5 lg:w-6 lg:h-6' }, true %}
        <span class="sr-only is-show-menu group-aria-expanded:hidden">
            Menu
        </span>
         <span class="sr-only is-close-menu hidden group-aria-expanded:block">
            Chiudi menu
        </span>
    </button>
    <!-- Mobile panel -->
    <div class="n7-primary-navigation__panel flex-col bg-white transition-all invisible w-[88%] lg:w-auto fixed lg:static lg:visible top-[--header-height] bottom-0 left-[12%] lg:left-0 border-l n7-border-primary lg:border-l-0 overflow-y-auto" id="mainNavPanel">
         <!-- Main nav -->
        <div class="n7-primary-navigation__module is-main lg:border-b-0">
            <ul class="n7-primary-navigation__list lg:flex lg:justify-end gap-4 xl:gap-8 has-dropdown-menu">
                {% render '@dropdown-menu', { label: 'Menu item 1',id: 'submenumenu-01', classes: 'n7-primary-navigation__item',listClasses: 'border-r-0 border-l-0 lg:border-r lg:border-l', items: [{label : 'voce 1'}, { label : 'voce 2'}] }, true %}
                {% render '@dropdown-menu', { label: 'Menu item 2',id: 'submenumenu-02', classes: 'n7-primary-navigation__item',listClasses: 'border-r-0 border-l-0 lg:border-r lg:border-l' }, true %}
                {% render '@dropdown-menu', { label: 'Menu item 3',id: 'submenumenu-03',classes: 'n7-primary-navigation__item',listClasses: 'border-r-0 border-l-0 lg:border-r lg:border-l' }, true %}
                {% render '@dropdown-menu', { label: 'Menu item 4',id: 'submenumenu-04', classes: 'n7-primary-navigation__item',listClasses: 'border-r-0 border-l-0 lg:border-r lg:border-l' }, true %}
                <!-- only link item -->
                <li class="n7-primary-navigation__item">
                    <a href="" class="w-full flex items-center p-3 gap-2 text-sm lg:text-base font-medium hover:underline focus:n7-content-primary">
                        Voce 1
                    </a>
                </li>
            </ul>
        </div>
        {% if hasSearchPanel %}
            <!-- Mobile search in panel -->
            <div class="n7-primary-navigation__module is-main lg:hidden">
                <form role="search" class="flex items-end p-3">
                    {% render '@input-field', { classes: 'flex-1',label: 'Cerca servizi, informazioni, aiuti...', inputId: 'inputSearchMobile', inputPlaceholder: 'Cerca', inputType: 'search', inputRadius: 'rounded-l-lg rounded-r-none'}, true %}
                    <button type="button" class="n7-btn n7-btn--secondary n7-btn--icon w-12 h-12">
                        <span class="sr-only">Cerca</span>
                        {% render '@icon--small', { id: 'mini--magnifying-glass', size: 'w-5 h-5' }, true %}
                    </button>
                </form>
            </div>
        {% endif %}
    </div>
    <div class="n7-primary-navigation__backdrop bg-black/25 top-[--header-height] lg:hidden"></div>
</nav>
{
  "navId": "mainNavPanel"
}
  • Content:
    /*
     *   This content is licensed according to the W3C Software License at
     *   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
     *
     *   Supplemental JS for the disclosure menu keyboard behavior
     */
    
    'use strict';
    
    // Helper function to find the closest ancestor with a specific tag name
    function findAncestor(element, tagName) {
      while (element) {
        if (element.tagName.toLowerCase() === tagName) {
          return element;
        }
        element = element.parentElement;
      }
      return null;
    }
    
    // function getButtonByControlledMenuId(id) {
    //   return this.topLevelNodes.find((button) => {
    //     const controlledMenuId = getControlledMenuId(button);
    //     return controlledMenuId === id;
    //   });
    // }
    
    class DisclosureNav {
      constructor(domNode) {
        this.rootNode = domNode;
        this.controlledNodes = [];
        this.openIndex = null;
        this.useArrowKeys = true;
        this.topLevelNodes = [
          ...this.rootNode.querySelectorAll(
            '.main-link, .dropdown-trigger'
          ),
        ];
    
        this.topLevelNodes.forEach((node) => {
          // handle button + menu
          if (
            node.tagName.toLowerCase() === 'button' &&
            node.hasAttribute('aria-controls')
          ) {
            const menu = node.parentNode.querySelector('ul');
    
            if (menu) {
              // save ref controlled menu
              this.controlledNodes.push(menu);
    
              // collapse menus
              node.setAttribute('aria-expanded', 'false');
              this.toggleMenu(menu, false);
    
              // attach event listeners
              menu.addEventListener('keydown', this.onMenuKeyDown.bind(this));
              node.addEventListener('click', this.onButtonClick.bind(this));
              node.addEventListener('keydown', this.onButtonKeyDown.bind(this));
            }
          }
          // handle links
          else {
            this.controlledNodes.push(null);
            node.addEventListener('keydown', this.onLinkKeyDown.bind(this));
          }
        });
    
        this.rootNode.addEventListener('focusout', this.onBlur.bind(this));
      }
    
      controlFocusByKey(keyboardEvent, nodeList, currentIndex) {
        switch (keyboardEvent.key) {
          case 'ArrowUp':
          case 'ArrowLeft':
            keyboardEvent.preventDefault();
            if (currentIndex > -1) {
              var prevIndex = Math.max(0, currentIndex - 1);
              nodeList[prevIndex].focus();
            }
            break;
          case 'ArrowDown':
          case 'ArrowRight':
            keyboardEvent.preventDefault();
            if (currentIndex > -1) {
              var nextIndex = Math.min(nodeList.length - 1, currentIndex + 1);
              nodeList[nextIndex].focus();
            }
            break;
          case 'Home':
            keyboardEvent.preventDefault();
            nodeList[0].focus();
            break;
          case 'End':
            keyboardEvent.preventDefault();
            nodeList[nodeList.length - 1].focus();
            break;
        }
      }
    
      // public function to close open menu
      close() {
        this.toggleExpand(this.openIndex, false);
      }
    
      onBlur(event) {
        var menuContainsFocus = this.rootNode.contains(event.relatedTarget);
        if (!menuContainsFocus && this.openIndex !== null) {
          this.toggleExpand(this.openIndex, false);
        }
      }
    
      onButtonClick(event) {
        var target = event.target;
    
        // Check if the target is not a button but is a descendant of a button
        if (target.tagName.toLowerCase() !== 'button') {
          var buttonAncestor = findAncestor(target, 'button');
    
          // If an ancestor button is found, trigger the click on that button
          if (buttonAncestor) {
            buttonAncestor.click();
            return; // Stop further processing since the click is handled
          }
        }
    
        var button = event.target;
        var buttonIndex = this.topLevelNodes.indexOf(button);
        var buttonExpanded = button.getAttribute('aria-expanded') === 'true';
        this.toggleExpand(buttonIndex, !buttonExpanded);
    
      }
    
      // getControlledMenuId(button) {
      //   return button.getAttribute('aria-controls');
      // }
    
    
      onButtonKeyDown(event) {
        var targetButtonIndex = this.topLevelNodes.indexOf(document.activeElement);
    
        // close on escape
        if (event.key === 'Escape') {
          this.toggleExpand(this.openIndex, false);
        }
    
        // move focus into the open menu if the current menu is open
        else if (
          this.useArrowKeys &&
          this.openIndex === targetButtonIndex &&
          event.key === 'ArrowDown'
        ) {
          event.preventDefault();
          this.controlledNodes[this.openIndex].querySelector('a').focus();
        }
    
        // handle arrow key navigation between top-level buttons, if set
        else if (this.useArrowKeys) {
          this.controlFocusByKey(event, this.topLevelNodes, targetButtonIndex);
        }
      }
    
      onLinkKeyDown(event) {
        var targetLinkIndex = this.topLevelNodes.indexOf(document.activeElement);
    
        // handle arrow key navigation between top-level buttons, if set
        if (this.useArrowKeys) {
          this.controlFocusByKey(event, this.topLevelNodes, targetLinkIndex);
        }
      }
    
      onMenuKeyDown(event) {
        if (this.openIndex === null) {
          return;
        }
    
        var menuLinks = Array.prototype.slice.call(
          this.controlledNodes[this.openIndex].querySelectorAll('a')
        );
        var currentIndex = menuLinks.indexOf(document.activeElement);
    
        // close on escape
        if (event.key === 'Escape') {
          this.topLevelNodes[this.openIndex].focus();
          this.toggleExpand(this.openIndex, false);
        }
    
        // handle arrow key navigation within menu links, if set
        else if (this.useArrowKeys) {
          this.controlFocusByKey(event, menuLinks, currentIndex);
        }
      }
    
      toggleExpand(index, expanded) {
        // close open menu, if applicable
        if (this.openIndex !== index) {
          this.toggleExpand(this.openIndex, false);
        }
    
        // handle menu at called index
        if (this.topLevelNodes[index]) {
          this.openIndex = expanded ? index : null;
          this.topLevelNodes[index].setAttribute('aria-expanded', expanded);
          this.toggleMenu(this.controlledNodes[index], expanded);
        }
      }
    
      toggleMenu(domNode, show) {
        if (domNode) {
          domNode.style.display = show ? 'block' : 'none';
    
          // if (show) {
          // Get the menu's position and dimensions
          const rect = domNode.getBoundingClientRect();
    
          // Check if the menu overflows on the right
          const isOverflowingRight = rect.right > window.innerWidth;
    
          // Check if the menu overflows on the left
          const isOverflowingLeft = rect.left < 0;
    
          // Add the appropriate class based on overflow
          domNode.classList.toggle('right-0', isOverflowingRight);
          domNode.classList.toggle('left-0', isOverflowingLeft);
          // }
        }
      }
    
      updateKeyControls(useArrowKeys) {
        this.useArrowKeys = useArrowKeys;
      }
    }
    
    /* Initialize Disclosure Menus */
    
    window.addEventListener(
      'load',
      function () {
        var menus = document.querySelectorAll('.has-dropdown-menu');
        var disclosureMenus = [];
    
        for (var i = 0; i < menus.length; i++) {
          disclosureMenus[i] = new DisclosureNav(menus[i]);
        }
      },
      false
    );
    
  • URL: /components/raw/primary-navigation/primary-navigation.js
  • Filesystem Path: components/03-molecules/primary-navigation/primary-navigation.js
  • Size: 7 KB

Primary navigation uses dropdown menu component.