
Mega Menu Builder
- 62 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Build a rich navigation mega menu with product images, category highlights, featured banners, and keyboard-accessible dropdowns for large catalogs.
About
Builds a mega-menu navigation with images, category highlights, featured banners, and accessible dropdowns suited to large catalogs. A frontend developer uses it to improve discoverability of a deep product catalog.
- Product images, category highlights, and featured banners in the menu
- Keyboard-accessible dropdown navigation
Mega Menu Builder by the numbers
- 62 all-time installs (skills.sh)
- Ranked #1,194 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill mega-menu-builderAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 62 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Build a rich navigation mega menu with product images, category highlights, featured banners, and keyboard-accessible dropdowns for large catalogs.
Files
Mega Menu Builder
Overview
Build a horizontal navigation bar that expands into full-width panels containing category columns, featured product cards, and promotional banners. The mega menu is driven by content manageable in your platform's admin, supports keyboard navigation and screen readers, and degrades gracefully to a mobile hamburger drawer.
When to Use This Skill
- When a store has 3+ top-level categories, each with significant sub-categories
- When the navigation needs to surface promotional content (seasonal banners, featured products) alongside category links
- When rebuilding navigation as part of a storefront redesign
- When the current dropdown menu is not accessible to keyboard or screen reader users
- When navigation content needs to be managed by a merchandiser without code deploys
Core Instructions
Step 1: Determine the merchant's platform and choose the right approach
| Platform | Recommended Approach | Why |
|---|---|---|
| Shopify | Configure nested menus in Navigation admin + use an OS2.0 theme that supports mega menus (Impulse, Empire, Prestige) or install Meteor Mega Menu app | Shopify's Navigation admin supports 3-level menus; premium themes like Impulse include built-in mega menu sections with image and banner support |
| WooCommerce | Use Max Mega Menu plugin (free/pro) or WP Mega Menu with your existing WordPress theme | Max Mega Menu integrates with any WordPress theme, adds image widgets and custom content to any menu item, and works with Elementor and Gutenberg |
| BigCommerce | Use Header & Navigation section in the Theme Editor with a theme that supports mega menus (Cornerstone Advanced, Merchant); or install Shogun page builder which includes mega menu blocks | BigCommerce themes vary in mega menu support; Cornerstone Advanced has a built-in mega menu; Shogun adds it to any theme |
| Custom / Headless | Build a data-driven mega menu component with hover/focus open logic, keyboard navigation (arrow keys, Escape), and a mobile accordion drawer | Full control over content model, animations, and accessibility patterns; see implementation below |
Step 2: Set up navigation content
---
Shopify
Configuring nested navigation:
1. Go to Online Store → Navigation 2. Open your Main menu (or create one) 3. For each top-level item that needs a mega panel, click Add menu item and nest sub-items under it using the indent controls 4. Shopify supports up to 3 levels of nesting (top → category → sub-category) 5. Save the menu
Enabling mega menu in a compatible theme:
If using a theme with built-in mega menu support (Impulse, Prestige, Empire): 1. Go to Online Store → Themes → Customize 2. Navigate to the Header section 3. Under Mega menu settings, select which top-level nav items should trigger the mega panel vs. a simple dropdown 4. For each mega panel, add image blocks, featured product blocks, and promotional banner blocks using the section editor
Using Meteor Mega Menu app (works with any Shopify theme): 1. Install from the Shopify App Store 2. In the app, select which menu items get mega panels 3. For each panel, add columns of links, product cards (pulled from your Shopify catalog), and image/banner blocks 4. The app injects the mega menu into your theme without editing theme code
---
WooCommerce
Using Max Mega Menu (free tier): 1. Install Max Mega Menu from WordPress.org 2. Go to Appearance → Menus and open your primary navigation menu 3. Enable Max Mega Menu for this menu via the Max Mega Menu Settings panel 4. For each top-level menu item that should have a mega panel:
- Click the Mega Menu toggle on the item
- Select the panel layout (e.g., 3 columns)
5. In each column, add menu items, widgets (images, HTML, WooCommerce product widgets), or text blocks 6. Go to Appearance → Max Mega Menu → Appearance to set the panel width to full-width and configure hover behavior
Integrating with Elementor: If your store uses Elementor, install Happy Addons or ElementsKit — both include a drag-and-drop mega menu builder that works within Elementor's visual editor.
---
BigCommerce
Cornerstone Advanced theme: 1. Go to Storefront → My Themes → Customize 2. In the Header section, find Navigation style and set it to Mega Menu 3. For each top-level category, you can add a featured image and banner in the Category settings (Products → Categories → [category] → Image) 4. BigCommerce automatically populates the mega panel with sub-categories; the theme renders them in a multi-column layout
Shogun page builder: 1. Install Shogun from the BigCommerce App Marketplace 2. Use Shogun's Header component to build a custom mega menu with full drag-and-drop control over columns, images, and links 3. Publish the header globally across all pages
---
Custom / Headless
Navigation component with hover/focus open logic:
// MegaNav.jsx
import { useState, useRef } from 'react';
export function MegaNav({ items }) {
const [activeItem, setActiveItem] = useState(null);
const closeTimer = useRef(null);
function openMenu(id) { clearTimeout(closeTimer.current); setActiveItem(id); }
function scheduleClose() { closeTimer.current = setTimeout(() => setActiveItem(null), 150); }
function cancelClose() { clearTimeout(closeTimer.current); }
return (
<nav aria-label="Main navigation">
<ul role="menubar" className="nav-bar">
{items.map(item => (
<li key={item.id} role="none"
onMouseEnter={() => item.megaMenu && openMenu(item.id)}
onMouseLeave={scheduleClose}>
<a href={item.url} role="menuitem"
aria-haspopup={item.megaMenu ? 'true' : undefined}
aria-expanded={activeItem === item.id ? 'true' : undefined}
onFocus={() => item.megaMenu && openMenu(item.id)}
onKeyDown={(e) => {
if ((e.key === 'ArrowDown' || e.key === 'Enter') && item.megaMenu) {
e.preventDefault();
openMenu(item.id);
document.querySelector(`#panel-${item.id} a`)?.focus();
}
if (e.key === 'Escape') setActiveItem(null);
}}>
{item.label}
</a>
{item.megaMenu && activeItem === item.id && (
<MegaPanel id={`panel-${item.id}`} panel={item.megaMenu}
onMouseEnter={cancelClose} onMouseLeave={scheduleClose}
onClose={() => setActiveItem(null)} />
)}
</li>
))}
</ul>
</nav>
);
}Mega panel layout (columns + featured products + banner):
function MegaPanel({ id, panel, onMouseEnter, onMouseLeave, onClose }) {
return (
<div id={id} className="mega-panel" role="region"
onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
<div className="mega-panel-inner">
<div className="mega-columns">
{panel.columns.map(col => (
<div key={col.heading} className="mega-column">
<p className="column-heading">{col.heading}</p>
<ul>
{col.links.map(link => (
<li key={link.url}><a href={link.url} onClick={onClose}>{link.label}</a></li>
))}
</ul>
</div>
))}
</div>
{panel.banner && (
<a href={panel.banner.url} className="mega-banner" onClick={onClose}>
<img src={panel.banner.image} alt={panel.banner.alt} loading="lazy" />
<span className="banner-cta">{panel.banner.cta}</span>
</a>
)}
</div>
</div>
);
}.mega-panel {
position: absolute; top: 100%; left: 0; width: 100vw;
background: #fff; border-top: 2px solid #e2e8f0;
box-shadow: 0 8px 24px rgba(0,0,0,0.12); z-index: 100;
}
.mega-panel-inner {
display: grid; grid-template-columns: 1fr 1fr 1fr 200px;
gap: 2rem; max-width: 1200px; margin: 0 auto; padding: 2rem;
}
@media (max-width: 768px) { .mega-panel { display: none; } }Step 3: Set up the mobile hamburger drawer
All platforms need a touch-friendly mobile navigation to replace the desktop mega menu:
- Shopify: Modern OS2.0 themes include a built-in mobile drawer — configure it in Online Store → Themes → Customize → Mobile Menu
- WooCommerce: Max Mega Menu has a built-in mobile mode that converts the mega menu to an accordion drawer; configure in Appearance → Max Mega Menu → Mobile Menu
- BigCommerce: Cornerstone's mobile navigation drawer is built in; configure the hamburger button position in the Theme Editor
- Custom: Build a
<dialog>orposition:fixedside drawer with accordion-style category expansion; applyoverflow:hiddento<body>when open
Best Practices
- Drive menu content from the CMS/admin — merchandisers should update banners and featured products without engineering help
- Use a 150 ms close delay — prevents the panel from disappearing when the cursor briefly leaves the nav while moving toward the panel
- Position the panel with `position:absolute` on the nav bar — not on the individual list item, so the panel spans full viewport width
- Lazy-load panel images — featured product and banner images should use
loading="lazy"since they are not above the fold - Test on touch devices — hover events do not fire on iOS/Android; mega menu apps and plugins handle this; for custom builds, use tap-to-open for top-level items on touch
Common Pitfalls
| Problem | Solution |
|---|---|
| Panel closes when moving cursor diagonally from nav item to panel | Use a 150–200 ms setTimeout delay before closing; cancel it when cursor enters the panel |
| Keyboard users cannot reach panel links | Use aria-haspopup and aria-expanded; move focus into the panel on Enter/Space/ArrowDown |
| Mobile drawer scrolls the body behind it | Apply overflow:hidden to <body> when drawer is open; restore on close |
| Banner images cause layout shift | Set explicit width and height attributes on banner <img> elements |
| Nav overlaps sticky content on scroll | Set position:sticky; top:0; z-index:50 on the nav; give the mega panel z-index:100 |
Related Skills
- @responsive-storefront
- @accessibility-commerce
- @product-categorization
- @storefront-theming
{
"context": "Tests whether the agent adds correct ARIA roles and attributes to the navigation bar, implements full keyboard navigation following the ARIA menu pattern, properly manages the close timer to prevent panel flicker, and opens the panel on focus.",
"type": "weighted_checklist",
"checklist": [
{
"name": "nav aria-label",
"max_score": 8,
"description": "The <nav> element has aria-label=\"Main navigation\" (or equivalent descriptive label)"
},
{
"name": "ul role menubar",
"max_score": 8,
"description": "The top-level <ul> element has role=\"menubar\""
},
{
"name": "li role none",
"max_score": 8,
"description": "Each top-level <li> element has role=\"none\""
},
{
"name": "a role menuitem",
"max_score": 8,
"description": "Each top-level <a> element has role=\"menuitem\""
},
{
"name": "aria-haspopup on trigger",
"max_score": 8,
"description": "Top-level anchors with an associated mega panel have aria-haspopup=\"true\""
},
{
"name": "aria-expanded state",
"max_score": 8,
"description": "Top-level anchors with an associated mega panel have aria-expanded set to \"true\" when the panel is open and \"false\" (or omitted) when closed"
},
{
"name": "Open on focus",
"max_score": 8,
"description": "The onFocus handler on top-level anchors opens the corresponding mega panel (same as hover)"
},
{
"name": "ArrowDown opens panel",
"max_score": 9,
"description": "Pressing ArrowDown (or Enter or Space) on a top-level item with a megaMenu opens the panel and moves focus to the first link inside it"
},
{
"name": "ArrowRight/Left between items",
"max_score": 8,
"description": "Pressing ArrowRight moves focus to the next top-level item; pressing ArrowLeft moves focus to the previous one (wrapping around)"
},
{
"name": "Escape closes panel",
"max_score": 8,
"description": "Pressing Escape while a panel is open closes it (sets activeItem to null)"
},
{
"name": "150ms close delay",
"max_score": 10,
"description": "The onMouseLeave handler uses a setTimeout of 150ms (or a value in the 150-200ms range) rather than immediately closing the panel"
},
{
"name": "Cancel close on panel enter",
"max_score": 9,
"description": "Entering the mega panel (onMouseEnter on the panel) cancels the pending close timer so the panel stays open"
}
]
}
Accessibility Audit and Fix for a Storefront Navigation Bar
Problem/Feature Description
A fashion e-commerce startup recently launched their site and received a failing score on an automated accessibility audit. Their primary complaint from assistive technology users is that the navigation dropdown menus are completely unreachable by keyboard — only mouse users can open them. The QA team also flagged that screen readers announce the nav structure incorrectly, with no indication that items have expandable sub-panels.
You have been handed their existing navigation component (provided below) and asked to bring it up to WCAG 2.1 AA. Specifically: screen readers must understand the menu structure and expansion state, keyboard users must be able to navigate between top-level items and open/close panels using standard keys, and the component must handle the close-on-move-away behavior cleanly without panels flickering when the cursor travels diagonally toward the panel.
Output Specification
Produce the following files:
MegaNav.jsx— the corrected navigation bar component with full keyboard support and correct ARIA attributesaccessibility-notes.md— a brief document listing each change you made and the specific ARIA or keyboard pattern it addresses
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/MegaNav.jsx =============== import { useState } from 'react'; import MegaPanel from './MegaPanel';
// ACCESSIBILITY ISSUES: This component has multiple a11y problems to fix. export function MegaNav({ items }) { const [activeItem, setActiveItem] = useState(null);
return ( <nav> <ul className="nav-bar"> {items.map((item, index) => ( <li key={item.id} onMouseEnter={() => item.megaMenu && setActiveItem(item.id)} onMouseLeave={() => setActiveItem(null)}> <a href={item.url}> {item.label} </a> {item.megaMenu && activeItem === item.id && ( <MegaPanel panel={item.megaMenu} onClose={() => setActiveItem(null)} /> )} </li> ))} </ul> </nav> ); }
{
"context": "Tests whether the agent correctly implements the mega panel data model, renders featured products and banners with required attributes, applies proper image loading strategy, uses the correct CSS grid layout, and wires up CMS data fetching with Next.js ISR caching.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Data model shape",
"max_score": 8,
"description": "The nav data structure includes columns (with heading and links), featuredProducts, and banner fields on the megaMenu object — matching the prescribed JSON shape"
},
{
"name": "Featured product image dimensions",
"max_score": 9,
"description": "Each featured product <img> element has explicit width and height attributes (e.g. width=\"80\" height=\"80\" or equivalent numeric values)"
},
{
"name": "Featured product name and price",
"max_score": 8,
"description": "Each featured product card renders both the product name and the product price"
},
{
"name": "Banner alt text",
"max_score": 8,
"description": "The banner <img> element uses the alt field from the data (not an empty alt or hardcoded text)"
},
{
"name": "Banner headline and CTA",
"max_score": 8,
"description": "The rendered banner includes both a headline element and a CTA link/button"
},
{
"name": "Banner image dimensions",
"max_score": 9,
"description": "The banner <img> element has explicit width and height attributes set to prevent layout shift"
},
{
"name": "Lazy-load panel images",
"max_score": 9,
"description": "Featured product images and/or banner images use loading=\"lazy\" attribute"
},
{
"name": "Close timer delay",
"max_score": 9,
"description": "The MegaNav hover-close logic uses a setTimeout delay of 150ms (or a value between 150-200ms) before setting the active item to null"
},
{
"name": "Panel role attribute",
"max_score": 8,
"description": "The mega panel container div has role=\"region\""
},
{
"name": "CSS grid layout",
"max_score": 9,
"description": "mega-panel.css (or equivalent) uses display:grid with a grid-template-columns value that includes at least three flexible columns and one fixed-width column (e.g. 1fr 1fr 1fr 200px)"
},
{
"name": "Mobile hide breakpoint",
"max_score": 8,
"description": "CSS includes a media query at max-width:768px (or similar mobile breakpoint) that hides the .mega-panel"
},
{
"name": "CMS revalidate interval",
"max_score": 7,
"description": "The navigation data fetching helper passes next: { revalidate: 300 } (or 5 minutes expressed as 300 seconds) in the fetch options"
}
]
}
Navigation Panel Components for an Online Apparel Store
Problem/Feature Description
A mid-size apparel retailer is rebuilding their storefront navigation. The merchandising team frequently rotates seasonal banners and swaps in featured products during promotions — they need to be able to do this without filing engineering tickets. The tech lead has decided to drive the navigation structure from a JSON payload returned by their headless CMS, so the same component code works for every campaign.
Your task is to build the React components that render a mega menu panel from that CMS payload. The panel should display category columns on the left, a featured-products strip in the middle, and a promotional banner on the right. The site has a performance-conscious audience and the tech lead cares about a smooth, fast page experience.
Output Specification
Produce the following files:
MegaPanel.jsx— the React component that renders a single mega menu panel given apanelprop (matching the structure in the provided data)MegaNav.jsx— a minimal navigation bar that renders a list of top-level items and mountsMegaPanelfor any item with amegaMenufield; it must handle both hover open/close and clean up any timersnavigation.js— a data-fetching helper that retrieves the navigation JSON from a CMS endpoint and is wired for Next.js ISR cachingmega-panel.css— CSS for the mega panel layout and the responsive breakpoint that handles small screens
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/nav-data-sample.json =============== [ { "id": "womens", "label": "Women's", "url": "/collections/womens", "megaMenu": { "columns": [ { "heading": "Clothing", "links": [ { "label": "Tops", "url": "/collections/womens-tops" }, { "label": "Bottoms", "url": "/collections/womens-bottoms" }, { "label": "Dresses", "url": "/collections/womens-dresses" } ] }, { "heading": "Shoes", "links": [ { "label": "Sneakers", "url": "/collections/womens-sneakers" }, { "label": "Boots", "url": "/collections/womens-boots" } ] } ], "featuredProducts": [ { "id": "prod_001", "name": "Summer Dress", "price": 89, "image": "/images/summer-dress.jpg", "url": "/products/summer-dress" }, { "id": "prod_002", "name": "Linen Blazer", "price": 120, "image": "/images/linen-blazer.jpg", "url": "/products/linen-blazer" } ], "banner": { "image": "/images/nav-banner-womens.jpg", "alt": "New summer collection", "url": "/collections/summer-2026", "headline": "Summer Collection", "cta": "Shop Now" } } }, { "id": "mens", "label": "Men's", "url": "/collections/mens", "megaMenu": null }, { "id": "accessories", "label": "Accessories", "url": "/collections/accessories", "megaMenu": { "columns": [ { "heading": "Bags", "links": [ { "label": "Totes", "url": "/collections/totes" }, { "label": "Backpacks", "url": "/collections/backpacks" } ] } ], "featuredProducts": [], "banner": { "image": "/images/nav-banner-accessories.jpg", "alt": "New accessories arrivals", "url": "/collections/new-accessories", "headline": "New Arrivals", "cta": "Explore" } } } ]
{
"context": "Tests whether the agent builds the mobile drawer with correct ARIA dialog semantics, implements accordion expansion with flattened column links, traps focus within the drawer, prevents body scroll while the drawer is open, and writes responsive CSS that hides the desktop mega panel at the mobile breakpoint.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Drawer role dialog",
"max_score": 8,
"description": "The mobile drawer container element has role=\"dialog\""
},
{
"name": "Drawer aria-label",
"max_score": 8,
"description": "The mobile drawer container has an aria-label attribute (e.g. aria-label=\"Navigation menu\")"
},
{
"name": "Drawer aria-modal",
"max_score": 8,
"description": "The mobile drawer container has aria-modal=\"true\""
},
{
"name": "Hamburger aria-expanded",
"max_score": 8,
"description": "The hamburger toggle button has an aria-expanded attribute that reflects the open/closed state"
},
{
"name": "Hamburger aria-controls",
"max_score": 8,
"description": "The hamburger button has an aria-controls attribute pointing to the drawer element's id"
},
{
"name": "Hamburger aria-label",
"max_score": 7,
"description": "The hamburger button has an aria-label that changes based on the open state (e.g. 'Open menu' / 'Close menu')"
},
{
"name": "Accordion flattens columns",
"max_score": 9,
"description": "When a category with a megaMenu is expanded in the drawer, links from ALL columns are rendered together in a single flat list (using flatMap or equivalent)"
},
{
"name": "Focus trap in drawer",
"max_score": 9,
"description": "The implementation-notes.md describes focus trapping (Tab cycling within drawer) OR the MobileNav.jsx implements a focus trap mechanism"
},
{
"name": "Escape closes drawer",
"max_score": 8,
"description": "Pressing Escape while the drawer is open closes it (either via a keydown handler or noted in implementation-notes.md)"
},
{
"name": "Body overflow hidden",
"max_score": 9,
"description": "overflow:hidden is applied to the <body> when the drawer is open and removed/restored when it closes"
},
{
"name": "Mega panel hidden on mobile",
"max_score": 9,
"description": "mega-panel.css includes a media query at max-width:768px (or similar) that sets display:none on the .mega-panel"
},
{
"name": "Panel full-width positioning",
"max_score": 9,
"description": "mega-panel.css positions the mega panel with position:absolute, left:0, and width:100vw so it spans the full viewport"
}
]
}
Mobile Navigation Drawer for a Storefront Mega Menu
Problem/Feature Description
A sportswear brand's desktop site has a working mega menu, but their mobile experience is broken. On phones, the full-width hover panels don't work (touch events differ from hover events), and the current fallback just hides the navigation entirely. Analytics show that over 60% of traffic is on mobile, so the team needs a proper mobile navigation drawer before their next product launch.
The solution should be a side drawer that slides in when a hamburger button is tapped. Inside the drawer, categories that have sub-links should expand accordion-style when tapped. When the drawer is open, users should not be able to accidentally interact with content behind it. The tech lead has also asked that the CSS for the desktop mega panel be updated so it is fully hidden at the mobile breakpoint, since the drawer replaces it entirely.
Output Specification
Produce the following files:
MobileNav.jsx— the mobile navigation drawer componentmega-panel.css— CSS that includes the desktop mega panel styles AND the responsive rule that hides it on small screens; also include any body-level styles needed when the drawer is openimplementation-notes.md— a short document describing how focus management works in the drawer and how body scroll is handled when the drawer is open
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/nav-data-sample.json =============== [ { "id": "running", "label": "Running", "url": "/collections/running", "megaMenu": { "columns": [ { "heading": "Men's Running", "links": [ { "label": "Shorts", "url": "/collections/mens-running-shorts" }, { "label": "Tops", "url": "/collections/mens-running-tops" }, { "label": "Shoes", "url": "/collections/mens-running-shoes" } ] }, { "heading": "Women's Running", "links": [ { "label": "Leggings", "url": "/collections/womens-leggings" }, { "label": "Sports Bras", "url": "/collections/sports-bras" }, { "label": "Shoes", "url": "/collections/womens-running-shoes" } ] } ], "featuredProducts": [], "banner": null } }, { "id": "training", "label": "Training", "url": "/collections/training", "megaMenu": { "columns": [ { "heading": "Equipment", "links": [ { "label": "Weights", "url": "/collections/weights" }, { "label": "Resistance Bands", "url": "/collections/bands" } ] } ], "featuredProducts": [], "banner": null } }, { "id": "sale", "label": "Sale", "url": "/collections/sale", "megaMenu": null } ]
{
"name": "finsi/mega-menu-builder",
"version": "0.1.0",
"summary": "Category navigation with mega menus, featured products, and promotional banners",
"skills": {
"mega-menu-builder": {
"path": "SKILL.md"
}
}
}