Multi-Level Dropdown Menu
Unlimited depth, build two-, three-, or four-level cascading dropdowns with no hard limits
A Magento 2 mega menu you build in an admin tree from category links, CMS pages, custom URLs and CMS blocks, with 1 to 4 columns per dropdown. Below 1024 px it switches to a slide-out mobile drawer.
Key Features:
Additional Services
Built-in from day one. No add-ons, no upsell, no licence keys to renew.
Unlimited depth, build two-, three-, or four-level cascading dropdowns with no hard limits
Bulk import / export, export the menu tree as JSON, edit externally, re-import
Drop any CMS block into a dropdown column, perfect for promo banners, featured products, or custom HTML
True mobile drawer, slides in from the left with smooth animations, not a shrunk desktop dropdown
Native Hyva template, Tailwind utilities + Alpine.js, no jQuery, no Knockout, no RequireJS
Vanilla JS template, zero jQuery / RequireJS coupling on the frontend path
Panth Mega Menu replaces the default Magento 2 top menu with a mega menu you build in an admin tree from category links, CMS pages, custom URLs and CMS blocks. Each dropdown can have 1 to 4 columns, and below 1024 px the menu becomes a slide-out mobile drawer.
Merchants build unlimited-depth menus visually with a tree editor, inject any CMS block into a dropdown column for promo banners or featured products, attach icons or images per item, and configure different menus per store view. Dynamic style controls tune color, spacing, hover delay, animation duration, and column widths per menu — without touching CSS.
The mega menu auto-detects Hyvä (Alpine.js plus Tailwind, smooth micro-interactions) and Luma (zero-dependency vanilla JS). A true mobile drawer replaces the desktop dropdown below a configurable breakpoint, with large touch targets and accordion-style sub-menus. The frontend is Full-Page-Cache aware, keyboard-navigable, ARIA-compliant, and ships with zero ObjectManager usage, following MEQP standards.
Compatible with Magento 2.4.4–2.4.9 and PHP 8.1–8.4, the extension is translation-ready, multi-store aware, and works alongside category, CMS, and custom URL nodes inside a single menu tree.
Best for:
Panth Mega Menu delivers a modern navigation system for Magento 2:
Panth Mega Menu replaces the default Magento top navigation with menus that are built in the admin and rendered by the module's own templates. A menu is a tree of items (category links, product links, CMS pages, custom URLs, custom HTML, CMS blocks, widget code and account links) with per-item icons, images, badges, colours, column layout, visibility rules and scheduling. The storefront renders the menu whose identifier is set in configuration (default "mainmenu") and removes Magento's catalog.topnav block once that identifier resolves to an active menu with visible items for the store view.
It is aimed at merchants who want to manage navigation without editing theme files, and at developers who need repositories, view models and templates to build on. The storefront menu uses one shared renderer, stylesheet and plain JavaScript file on Hyva and Luma; older Hyva and Luma template sets are still shipped for themes that override them.
Product page: Magento 2 Mega Menu
aria-current="page", its top-level item shows the active bar, and the mobile drawer opens the branch that contains it.X-Robots-Tag: noindex, nofollow.panth_menu_demo_featured, panth_menu_demo_promo, panth_menu_demo_newsletter) can be created from the admin for testing block injection.pmm/render.phtml renders the menu, view/frontend/web/css/pmm.css styles it and view/frontend/web/js/pmm.js (plain JavaScript, no Alpine.js or jQuery) drives hover intent, click and tap, keyboard navigation, the overflow arrows and the mobile drawer. See "Storefront menu" below.Helper\Theme) treats a store as Hyva when the Hyva_Theme module is enabled or the theme path contains "hyva", otherwise as Luma.panth_megamenu and panth_megamenu_<menu_id>. A "Flush Cache" admin action cleans the full_page and block_html cache types.Saving, importing, toggling, restoring or deleting a menu cleans the cache entries tagged panth_megamenu (menu block cache and full page cache entries of pages that show a menu). The "Flush Cache" action in the menu grid is still available.
The "Store View" field (General Information) decides where a menu is shown: All Store Views (store ID 0) or the selected store views. When a menu is assigned to some store views only, the other store views keep their native navigation (or another menu with the same identifier assigned to them). The identifier itself stays unique.
http, https, mailto and tel schemes are rendered; any other scheme (for example javascript: or data:) is replaced with #. For "My Account Dashboard", "My Orders" and "My Wishlist" the builder fills the URL field with /customer/account, /sales/order/history or /wishlist.#).An item is rendered only when all of the following hold: it is active; its level is below Maximum Menu Depth; the current time is within its start and end date (both are read in the store timezone; a date with a time applies from or until that moment, a date without a time covers the whole day); for category items, the category is enabled and belongs to the store's root category; and its device flag is set (Show on Desktop for the menu bar; in the mobile drawer Show on Mobile applies below 768px and Show on Tablet from 768px).
Parent items with children open a dropdown panel. Each second-level item is a column; Column Width can widen a column. CMS blocks and custom HTML placed on sub-items fill a column of the panel. Custom HTML is passed through the CMS page filter, so CMS directives such as {{store url=""}} and {{widget ...}} are processed; the HTML itself is not stripped, so only trusted admin users should be allowed to edit menus.
Images are uploaded from the builder to pub/media/panth/megamenu/; allowed extensions are jpg, jpeg, gif, png and webp, the file MIME type must be one of the matching image types, and the name is checked against Panth\Core\Security\UploadExtensionPolicy. SVG files cannot be uploaded. Icons are entered as a class from the shipped Font Awesome, LineIcons or Material Icons stylesheets, or as an emoji. Inline SVG icons that contain scripts, event handler attributes, javascript: URLs, foreignObject, embedded frames or character references are not rendered.
luma/menu.phtml (Luma, also used by luma/desktop/menu.phtml), the Panth Infotech theme template Panth_MegaMenu::menu.phtml (Hyva, with the category tree as fallback when no menu resolves) and preview.phtml collect the item tree and the configuration and render it through pmm/render.phtml. The stylesheet css/pmm.css is added to every storefront page by default.xml; the script js/pmm.js is loaded once by the first menu on the page. Every menu instance gets its own ids, so several menus (header plus CMS directives) work on one page.
Desktop (Hyva from 1024px, Luma above Mobile Breakpoint):
#E5E7EB border, 8px radius, one shadow, 14px text, #0F766E hover text and #F0FDFA hover tint.aria-current="page" items show the bar too. Hover Effect maps to: underline and slide (bar on hover), highlight (tint on hover), fade (80% opacity on hover); glow and grow fall back to the colour change.# or empty only toggle their dropdown.# item, Space and Arrow Down open the dropdown and focus its first link, Arrow Up opens it at the last link, Arrow Left and Right move between top-level items, Home and End jump to the first and last item, arrows move inside the panel and Escape closes it and returns focus to the item. Triggers carry aria-haspopup, aria-expanded and aria-controls.On Luma, a header menu sits between the logo and the search box and mini cart from 768px up; below 768px the menu button takes the place of the Luma menu toggle at the left of the logo. Font Awesome icons used by menu items are loaded from the module on Luma.
Mobile (below the same breakpoints): the menu button opens an off-canvas drawer (left or right, following Mobile Menu Position) with a backdrop, both at z-index 70. The drawer is moved to the end of <body>, focus goes to the close button and returns to the menu button on close, Tab stays inside the drawer, Escape and the backdrop close it, and the page does not scroll while it is open. While the drawer is open the <html> element has the class panth-overlay-open, which floating buttons use to hide. Sub-menus open as an accordion with 48px rows, 16px text and a chevron button per item; custom HTML and CMS blocks are shown as a tinted tile.
Per-item text, hover text, hover background, background, font family, size, weight, text transform, padding, margin, width, height, border, border radius, box shadow, text shadow and opacity values are applied when they are plain CSS values; values containing ;, braces, quotes, url( or expression( are ignored.
The "Preview" button opens an admin popup with Desktop (1280px, scaled to fit), Tablet (768px) and Mobile (375px) widths and a Refresh button. The popup posts the current, unsaved menu to the frontend route panth_menu/preview/index inside an isolated frame; links in the frame open in a new tab. The route only renders for requests that carry a valid preview_token: a signed token (HMAC-SHA256 over an expiry time with the deployment crypt/key) that the admin menu edit pages embed when they are loaded and that is valid for one hour (Model\PreviewAccess::TOKEN_LIFETIME). Reload the edit page to get a new token. A one-time token from panth_menu/menu/previewToken together with menu_id is also accepted. Requests without a valid token get the 404 page. POST requests (unsaved items_json) fail CSRF validation unless they carry a valid token, and unsaved items are only read from the POST body. The preview page uses the empty page layout, removes the regular menu blocks, renders the requested menu (saved items for menu_id, or the unsaved items from the POST body) with the same storefront markup, stylesheet and script inside preview-container.phtml, so Desktop shows the dropdowns and Tablet and Mobile show the drawer exactly as the storefront does. The page uses its own root template (preview/root.phtml) that outputs the storefront head assets and only the preview container, the menu custom CSS block and the Hyva Alpine.js script, so the store header, footer and other page blocks are not shown. It works on Hyva and Luma and is sent with no-cache headers.
The menu builder page loads a Tailwind stylesheet and the Inter font shipped with the module (view/adminhtml/web/css/tailwind.min.css, view/adminhtml/web/fonts/inter.woff2) instead of the Tailwind CDN and Google Fonts. Item titles, URLs, CSS classes, colours, icons and picker entries are HTML-escaped before the builder inserts them into the page. The Delete, Toggle, Duplicate, Flush Cache and Create Demo Blocks admin actions accept POST requests only; Toggle, Duplicate and Create Demo Blocks require the admin form key.
menu_<identifier>_<timestamp>.json with the menu data and items.menu and items must both be objects or arrays.panth_menu/menu/importCategories) creates items from the category tree down to a maximum level.view/frontend/layout/default.xml adds css/pmm.css to the page head and megamenu.main (Block\Menu, template Panth_MegaMenu::luma/menu.phtml) to header-wrapper after the logo, guarded by ifconfig="panth_megamenu/general/enabled".view/frontend/layout/default_luma.xml declares megamenu.main in header.container with Panth_MegaMenu::luma/desktop/menu.phtml.view/frontend/layout/default_hyva.xml removes megamenu.main; on Hyva the theme layout is expected to add Block\Menu with the Hyva templates (see the comment in that file).view/frontend/layout/panth_menu_preview_index.xml builds the preview page.pmm/render.phtml (shared storefront markup), hyva/menu.phtml, hyva/desktop/menu.phtml, hyva/desktop/item.phtml, hyva/desktop/item_recursive.phtml, hyva/mobile/menu.phtml, hyva/mobile/item.phtml, hyva/mobile/drawer.phtml, hyva/sticky/header.phtml, hyva/css/styles.phtml, hyva/js/alpine-components.phtml, hyva/menu_mobile_premium.phtml, luma/menu.phtml, luma/desktop/menu.phtml, luma/desktop/item.phtml, luma/item.phtml, luma/mobile/menu.phtml, luma/mobile/menu_simple.phtml, luma/mobile/item.phtml, luma/sticky/header.phtml, luma/css/styles.phtml, luma/js/knockout-components.phtml, pmenu/menu.phtml, pmenu/item.phtml, preview.phtml, preview-container.phtml, js-init.phtml and theme-config.phtml.pmenuDesktop, pmenuMobile and the legacy aliases panthMegaMenu, megaMenu, megaMenuWidget, all pointing at Panth_MegaMenu/js/pmenu-desktop or pmenu-mobile. Admin alias: menuPreview.Block\Menu::getCacheKeyInfo() keys the block cache by store, menu identifier, theme and customer ID, and getIdentities() always returns panth_megamenu and, once a menu is loaded, panth_megamenu_<menu_id>. Model\Menu uses the cache tags panth_megamenu_menu and panth_megamenu and returns them (plus the ID variants) from getIdentities(), so saving or deleting a menu cleans the block cache and the full page cache entries of pages that show a menu. Helper\Data::cleanMenuCache() cleans entries by those tags and Helper\Data::flushMenuCache() cleans the full_page and block_html cache types.
USER_GUIDE.md covers installation, checking that the module is active, the configuration screens, the menu builder, item types, column layouts, CMS block injection, mobile drawer behaviour, per-store menus, troubleshooting and a short CLI reference.
See CHANGELOG.md.
| Requirement | Supported |
|---|---|
| Magento Open Source | 2.4.4 to 2.4.8 (as published on the product page) |
| Adobe Commerce | 2.4.4 to 2.4.8 (as published on the product page) |
| PHP | 8.1, 8.2, 8.3, 8.4 (`~8.1.0 |
| Themes | Hyva and Luma (one shared storefront renderer, pmm/render.phtml) |
Composer constraints on Magento packages: magento/framework ^103.0, magento/module-backend ^102.0, magento/module-store ^101.1, magento/module-cms ^104.0, magento/module-catalog ^104.0, magento/module-config ^101.2, magento/module-ui ^101.2.
mage2kishan/module-core ^1.0.17 (installed by Composer with this package). This module hangs its admin menu under Panth_Core::panth_extensions, registers itself with Panth\Core\ViewModel\ThemeConfig and uses Panth\Core\Security\UploadExtensionPolicy for image uploads.hyva-themes/magento2-default-theme when the Hyva templates are wantedcomposer require mage2kishan/module-mega-menu
bin/magento module:enable Panth_Core Panth_MegaMenu
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
setup:di:compile is only needed in production mode. The module ships JavaScript, CSS, fonts and images under view/adminhtml/web, view/base/web and view/frontend/web, so static content has to be deployed.
Check the result with:
bin/magento module:status Panth_MegaMenu
setup:upgrade creates the module tables and runs the data patch Setup\Patch\Data\AddDefaultStoreRelations, which assigns store ID 0 (all store views) to any existing menu that has no store relation.
Admin path: Stores > Configuration > "Panth Extensions" > "MegaMenu". In etc/adminhtml/system.xml the tab label is prefixed with a rocket emoji. All fields can be set at default, website and store view scope. Config paths follow the pattern panth_megamenu/<group>/<field>; the field id is shown in brackets in the tables below.
panth_megamenu/general)| Setting | Default | What it does |
|---|---|---|
Enable MegaMenu (enabled) |
Yes | Master switch. When set to No the module renders nothing and the default Magento navigation stays in place. This includes menus placed in CMS content with a {{block class="Panth\MegaMenu\Block\Menu" ...}} directive. |
Menu Identifier (menu_identifier) |
mainmenu | Identifier of the menu record to render. Shown when Enable MegaMenu is Yes. |
Mobile Breakpoint (px) (mobile_breakpoint) |
1024 | Luma storefront: widths up to this value show the menu button instead of the menu bar. The Hyva header always switches below 1024px to match the theme header. Shown when Enable MegaMenu is Yes. |
panth_megamenu/styling)| Setting | Default | What it does |
|---|---|---|
Hover Effect (hover_effect) |
Underline | Effect applied to menu items on hover. Options: None, Underline, Fade, Highlight, Slide, Glow, Grow. |
Custom CSS (custom_css) |
empty | CSS rules for the menu, without <style> tags. |
The group comment states that menu colours are taken from the Hyva theme's Tailwind theme-config.json. The module ships its default pmenu-* design tokens in etc/theme-config.json.
panth_megamenu/display)| Setting | Default | What it does |
|---|---|---|
Animation Type (animation_type) |
Fade | Animation used when a dropdown opens or closes. Options: None, Fade, Slide, Grow. |
Animation Duration (ms) (animation_duration) |
200 | Duration of the dropdown and hover animations (0-1000). |
Hover Intent Delay (ms) (hover_intent_delay) |
150 | Delay before a dropdown opens on hover. |
Show Icons (show_icons) |
Yes | Display item icons when set. |
Show Images (show_images) |
Yes | Display item images in dropdown panels. |
Maximum Menu Depth (max_depth) |
5 | Number of menu levels rendered. Top-level items are the first level, so 3 shows top-level items and two levels below them. Every storefront template applies the same limit. |
Show Category Product Count (show_category_count) |
No | Show the product count next to category names. |
Enable Custom Blocks (enable_custom_blocks) |
Yes | Allow CMS blocks inside dropdowns. |
panth_megamenu/mobile)| Setting | Default | What it does |
|---|---|---|
Mobile Menu Position (position) |
Left | Slide-in side of the mobile panel: Left or Right. |
The mobile drawer always has a backdrop, an accordion for sub-menus and a close button.
panth_megamenu/performance)| Setting | Default | What it does |
|---|---|---|
Enable Menu Cache (cache_enabled) |
Yes | Cache the rendered menu block. When Yes, the block cache lifetime is taken from Cache Lifetime. |
Cache Lifetime (seconds) (cache_lifetime) |
3600 | Lifetime of the cached menu block. Shown when Enable Menu Cache is Yes. |
panth_megamenu/advanced)| Setting | Default | What it does |
|---|---|---|
Custom JavaScript (custom_js) |
empty | JavaScript added for the menu, without <script> tags. |
Default behaviour after installation: the module is enabled and looks for an active menu with the identifier mainmenu. Until such a menu exists for the store view, Luma keeps its native category menu (catalog.topnav), and the Hyva header shows the category tree with the module's menu markup in place of the theme menu (topmenu_desktop, topmenu_mobile). When Enable MegaMenu is No, both storefronts show their native category menu. When the menu resolves, the plugin removes them and adds the body class panth-megamenu-active, which the Luma styles use to hide the native nav toggle.
Admin menu entries: "Panth Extensions" > "Mega Menu" > "Menu Items" (route panth_menu/menu/index) and "Panth Extensions" > "Mega Menu" > "Configuration" (opens the MegaMenu configuration section).
The module does not add category attributes to the category edit form.
bin/magento module:disable Panth_MegaMenu
composer remove mage2kishan/module-mega-menu
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
After removal the six panth_megamenu_* tables, the configuration rows under panth_megamenu/ in core_config_data, uploaded images in pub/media/panth/megamenu/ and any demo CMS blocks remain and have to be dropped or deleted manually. No product or category attributes were added. Panth_Core stays installed if other packages depend on it.
Commercial software license. See LICENSE.txt in this repository.
Panth_MegaMenu; Composer package: mage2kishan/module-mega-menu (version 1.0.12); PHP namespace: Panth\MegaMenu.etc/di.xml): Api\MenuRepositoryInterface (save, getById, getByIdentifier, getList, delete, deleteById), Api\ItemRepositoryInterface (adds getMenuTree, moveItem), Api\MenuVersionRepositoryInterface (adds getByMenuId), and the data interfaces Api\Data\MenuInterface, Api\Data\ItemInterface, Api\Data\MenuVersionInterface with their search results interfaces.Model\MenuRepository::save() creates a panth_megamenu_menu_version row on every save.Block\Menu (getCurrentMenu, getCurrentMenuTree, getMenuConfig, getMenuConfigJson, getCacheKeyInfo, getIdentities), Block\MenuItem, Block\Navigation, Block\MobileMenu, Block\StickyMenu, Block\Preview.ViewModel\Menu (getMenuItems, getItemUrl, isItemVisible, getChildren, renderItemContent, getBadgeHtml, getBreadcrumbTrail), ViewModel\Config, ViewModel\MobileConfig, ViewModel\StickyConfig, ViewModel\ItemRenderer.Helper\Data (configuration getters, cleanMenuCache, flushMenuCache, getMenuCacheTags), Helper\Theme (isHyva, isLuma, getCurrentTheme, getTemplateForTheme, getThemeConfig), Helper\MenuRenderer (renderDesktopMenu, renderDesktopMenuLuma, renderCmsBlock, renderIcon, renderImage, sanitizeUrl, filterContent, sanitizeTree), Helper\Config (reads panth_megamenu/mobile/mobile_enabled for isMobileEnabled()).Model\PreviewAccess creates and validates the signed preview tokens. Block\Menu and Block\Preview pass the item tree through Helper\MenuRenderer::sanitizeTree() (URL scheme check and CMS filter for custom_content) before templates render it.etc/di.xml): Plugin\RemoveDefaultNavigation (after Magento\Framework\View\Layout::generateElements, removes catalog.topnav, topmenu_desktop, topmenu_mobile when the module is enabled and an identifier is set); Plugin\ThemeResolver on Magento\Framework\View\DesignInterface; Plugin\DisableBackendValidation on Magento\Backend\App\Request\BackendValidator (skips validation for the read-only GetCategories, ImportCategories and GetIcons admin actions; for CustomSave it copies form_key from the JSON body into the request so the normal form key check applies).etc/frontend/di.xml registers the module with Panth\Core\ViewModel\ThemeConfig; etc/theme-config.json holds the default pmenu-* tokens.etc/adminhtml/di.xml declares the virtual type Panth\MegaMenu\ItemImageUploader (Magento\Catalog\Model\ImageUploader, base path panth/megamenu/item, jpg, jpeg, gif, png and webp). No controller currently uses it.panth_menu_listing_data_source (Model\ResourceModel\Menu\Grid\Collection) and panth_megamenu_item_listing_data_source (virtual type over panth_megamenu_item).panth_menu (etc/adminhtml/routes.xml) and frontend panth_menu (etc/frontend/routes.xml).Controller\Adminhtml\Menu: Index, Edit, CustomEdit, Save, CustomSave, Delete, Duplicate, Toggle, Export, Import, ImportForm, ImportCategories, GetCategories, GetIcons, Upload, Validate, PreviewToken, Restore, VersionView, FlushCache, CreateDemoBlocks; under Controller\Adminhtml\Version: Restore, Export, Delete. Frontend: Controller\Preview\Index.Panth_MegaMenu::panth_extensions, Panth_MegaMenu::menu, Panth_MegaMenu::menu_items, Panth_MegaMenu::menu_save, Panth_MegaMenu::menu_delete, Panth_MegaMenu::menu_builder, Panth_MegaMenu::item_save, Panth_MegaMenu::item_delete, Panth_MegaMenu::menu_version_restore, Panth_MegaMenu::menu_version_view, Panth_MegaMenu::config, Panth_MegaMenu::design_config.etc/db_schema.xml): panth_megamenu_menu (menu records including items_json and container styling), panth_megamenu_item (normalised item rows with foreign keys to categories, CMS pages and products), panth_megamenu_store (menu to store view relation), panth_megamenu_customer_group (menu to customer group relation), panth_megamenu_cache (render cache rows keyed by menu, store and customer group), panth_megamenu_menu_version (version history). The storefront reads items from items_json.panth_megamenu, panth_megamenu_<menu_id>; model tags panth_megamenu_menu, panth_megamenu_item, panth_megamenu_menu_version.events.xml and no cron jobs are declared. Observer\ModuleInitialization, Model\InitFlag, Helper\Initialization and Helper\Webhook ship with the module but are not referenced by any configuration file.| Module Category | Theme & UI |
|---|---|
| Best For | All Sizes |
Yes. The module ships with two purpose-built templates, Alpine.js + Tailwind for Hyva and vanilla JS for Luma, and auto-switches based on your active storefront theme.
Yes. The drag-and-drop tree builder supports unlimited nesting. Desktop dropdowns render in multi-column layouts; mobile collapses deeper levels into accordion sections.
Yes. Drop any CMS block into any column of a parent item's dropdown. Perfect for promo banners, featured products, or custom HTML.
Yes. Menus are store-view scoped. You can build a unique menu per store view or copy a menu from one store view to another with one click.
No. The menu HTML is cached in Full-Page-Cache and invalidated only when underlying categories or CMS blocks change. The entire tree loads in a single DB query with EAV joins resolved in one shot.
Yes. The module is fully keyboard navigable with arrow keys, Enter, and Escape, and includes complete ARIA attributes for screen readers.
Optional. The Replace Native Menu setting hides Magento's default top-menu and renders the Panth menu in its place. Disable it to keep both running side-by-side for migration purposes.
No. The codebase uses full constructor injection and passes MEQP (Magento Extension Quality Program) checks with zero ObjectManager usage.
Yes. The full source is on GitHub at github.com/mage2sk/module-mega-menu.
Yes. All user-facing strings use Magento's standard __() translation function and can be translated to any language.
Talk to Kishan directly: written quote, scope and timeline within 24 hours. No sales call.
Mega Menu for Magento 2, Multi-Level Dropdown Navigation