Skip to main content

Menu 4-panel

This 4-panel menu transforms into sliding panels on mobile, making it ideal for content-heavy websites. Each panel is activated using a data-submenu attribute and an ID, allowing you to easily modify your HTML structure while maintaining the logic.

Demo

Installation

Import the function into the JavaScript file of your project

import { MenuFourPanel } from "@overdog/fn"

Create and initialize an instance

new MenuFourPanel("#menu-four-panel", {
   // your options goes here
}).init()

Add the Tailwind variants to the plugins section of your config file.

If you are using multiple elements from Overdog FN that require the same variants, you only need to add them once. You can also modify the data attributes added to each function using the attributes parameter {}.

module.exports = {
   // ...
   plugins: [
      plugin(function ({ addVariant }) {
         addVariant("is-open", "&[data-fn-is-open]")
         addVariant("parent-is-open", "[data-fn-is-open] &")
      })
   ]
}
Note: If you want a mega-nav like in the example, don't forget to also import the mega-nav and add the corresponding Tailwind CSS variants. Refer to the Mega-Nav section for details

Twig template Code

{# 
-------------------------------------------------------------------
Example based on a Craft CMS structure with multiples levels
You can use it with any content modeling 
(categories, global entries field, etc.)
-------------------------------------------------------------------
#}

{% set pages = craft.entries.section('structurePets').all() %}


<div class="relative w-full h-16 z-40 bg-blue-500">
   <div id="nav-buttons-group" class="container flex items-center h-full justify-end z-50 text-6">
        <button 
         data-fn-nav-button="1" 
         class="rounded-full bg-white h-10 w-10"  
         type="button" 
         aria-label="Button 1" 
         aria-haspopup="true" 
         aria-expanded="false">
         1
      </button>
   </div>
   <nav 
      data-fn-nav-panel="1"
      class="fixed z-30 top-0 left-0 w-full h-full -translate-y-full overflow-y-scroll overflow-x-hidden bg-[#dcdee6]
      nav-open-1:translate-y-0 nav-open-1:transition-transform nav-open-1:duration-300 nav-open-1:ease-nav-in"
   >
   {% if pages|length %}
      <div id="menu-four-panel" class="w-full mx-auto md:w-[90%] h-full px-[20px] relative" role="navigation" aria-label="{{ 'Main menu'|t }}">
         {# this UL is main menu level 1 #}
         <ul
            data-fn-menu-list 
            class="absolute left-0 min-h-full w-full md:w-1/4 pt-44 pb-4 px-[20px]"
            role="menubar" 
         >
         {% nav page in pages %}
            <li data-fn-menu-item role="none">
               {% ifchildren %}
               <button 
                  id="menu-button-{{ loop.index }}"
                  data-fn-submenu="submenu-{{ loop.index }}"
                  data-fn-menu-button="button-{{ loop.index }}"
                  class="items-center flex justify-between px-4 py-2 w-full after:content-['ยป'] after:shrink-0 after:text-0.7em is-open:bg-[#fff]"
                  aria-haspopup="true" 
                  aria-expanded="false">
                  {{ page.title }}
               </button>
               {# this UL is submenu level 2-3-4 #}
               <ul 
                  id="submenu-{{ loop.index }}" 
                  role="menubar"
                  data-fn-menu-list
                  class="absolute top-0 pt-44 pb-12 px-[20px] min-h-full bg-[#fff] w-[calc(100%-20px)] border-l border-[#e3e3e3]
                  translate-x-full transition-transform
                  is-open:translate-x-0
                  md:bg-transparent md:w-full md:left-full md:transform-none md:hidden md:border-0
                  md:is-open:block md:is-open:animate-fade-in md:is-open:transform-none"
               >
                  {# mobile back button for sliding panels #}
                  <li data-fn-menu-item role="none">
                     <button
                        data-fn-submenu="submenu-{{ loop.index }}" 
                        data-fn-menu-back="menu-button-{{ loop.index }}" 
                        class="bg-[#e3e3e3] mb-1 px-4 py-2 md:hidden">
                        {{ 'Back'|t }}
                     </button>
                  </li>
                  {# Repeat the markup inside nav tag for all sub-levels item in the query #}
                  {% children %}
               </ul>
               {% endifchildren %}
               {# if page has no descendants - show a url instead of a parent button #}
               {% if page.hasDescendants() == false %}
                  <a 
                     role="menuitem" 
                     class="items-center flex justify-between px-4 py-2 w-full" 
                     href="{{ page.url }}">
                     {{ page.title }}
                  </a>
               {% endif %}
            </li>
         {% endnav %}
         </ul>
      </div>
   {% endif %}
   </nav>
</div>

Options