fix: responsive mega menu

This commit is contained in:
mohamad
2026-05-31 10:30:36 +03:30
parent 52516d5a5a
commit 7726b0b6ec
2 changed files with 125 additions and 14 deletions
+57 -8
View File
@@ -2926,15 +2926,50 @@ a.citation-count-badge:hover {
font-size: 0.95rem; font-size: 0.95rem;
} }
.nav-item.has-megamenu:hover .nav-arrow {
transform: none;
}
.nav-item.has-megamenu.open .nav-arrow {
transform: rotate(180deg);
}
.megamenu { .megamenu {
position: static; position: static;
background: rgba(255, 255, 255, 0.03); max-height: 0;
border: 1px solid var(--glass-border); overflow: hidden;
margin: 0;
padding: 0;
border: none;
border-radius: var(--radius-md); border-radius: var(--radius-md);
transform: none; transform: none;
box-shadow: none; box-shadow: none;
backdrop-filter: none; backdrop-filter: none;
-webkit-backdrop-filter: none; -webkit-backdrop-filter: none;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.nav-item.has-megamenu:hover .megamenu {
opacity: 0;
visibility: hidden;
max-height: 0;
pointer-events: none;
transform: none;
}
.nav-item.has-megamenu.open .megamenu {
max-height: 2000px;
overflow: visible;
margin-top: 0.25rem;
padding: 0;
background: rgba(255, 255, 255, 0.03);
border: 1px solid var(--glass-border);
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: none;
} }
.megamenu-inner { .megamenu-inner {
@@ -2956,14 +2991,28 @@ a.citation-count-badge:hover {
max-width: none; max-width: none;
} }
.megamenu-product-item.has-subproducts .megamenu-sublist { .megamenu-product-item.has-subproducts:hover .megamenu-sub-chevron,
max-height: none; .megamenu-product-item.has-subproducts:focus-within .megamenu-sub-chevron {
opacity: 1; transform: none;
border-top-color: var(--glass-border); color: var(--text-muted);
} }
.nav-item.has-megamenu:hover .megamenu { .megamenu-product-item.has-subproducts:hover .megamenu-sublist,
transform: none; .megamenu-product-item.has-subproducts:focus-within .megamenu-sublist {
max-height: 0;
opacity: 0;
border-top-color: transparent;
}
.megamenu-product-item.has-subproducts.open .megamenu-sub-chevron {
transform: rotate(180deg);
color: var(--accent-blue-light);
}
.megamenu-product-item.has-subproducts.open .megamenu-sublist {
max-height: 320px;
opacity: 1;
border-top-color: var(--glass-border);
} }
.sub-product-grid { .sub-product-grid {
+68 -6
View File
@@ -12,6 +12,12 @@ const SELECTORS = {
citationCopy: '.citation-copy', citationCopy: '.citation-copy',
}; };
const MOBILE_NAV_MQ = window.matchMedia('(max-width: 768px)');
function isMobileNav() {
return MOBILE_NAV_MQ.matches;
}
function initNavbarScroll() { function initNavbarScroll() {
const navbar = document.querySelector(SELECTORS.navbar); const navbar = document.querySelector(SELECTORS.navbar);
if (!navbar) return; if (!navbar) return;
@@ -28,6 +34,26 @@ function initNavbarScroll() {
onScroll(); onScroll();
} }
function closeMobileNavMenu() {
const toggle = document.querySelector(SELECTORS.navbarToggle);
const menu = document.querySelector(SELECTORS.navbarMenu);
const productsItem = document.querySelector(SELECTORS.productsNavItem);
if (!toggle || !menu) return;
menu.classList.remove('open');
toggle.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
if (productsItem) {
productsItem.classList.remove('open');
const productsTrigger = productsItem.querySelector('.nav-link');
if (productsTrigger) productsTrigger.setAttribute('aria-expanded', 'false');
productsItem.querySelectorAll('.megamenu-product-item.has-subproducts.open').forEach((item) => {
item.classList.remove('open');
});
}
}
function initMobileMenu() { function initMobileMenu() {
const toggle = document.querySelector(SELECTORS.navbarToggle); const toggle = document.querySelector(SELECTORS.navbarToggle);
const menu = document.querySelector(SELECTORS.navbarMenu); const menu = document.querySelector(SELECTORS.navbarMenu);
@@ -37,22 +63,26 @@ function initMobileMenu() {
const isOpen = menu.classList.toggle('open'); const isOpen = menu.classList.toggle('open');
toggle.classList.toggle('open', isOpen); toggle.classList.toggle('open', isOpen);
toggle.setAttribute('aria-expanded', String(isOpen)); toggle.setAttribute('aria-expanded', String(isOpen));
if (!isOpen) {
const productsItem = document.querySelector(SELECTORS.productsNavItem);
if (productsItem) {
productsItem.classList.remove('open');
const productsTrigger = productsItem.querySelector('.nav-link');
if (productsTrigger) productsTrigger.setAttribute('aria-expanded', 'false');
}
}
}); });
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && menu.classList.contains('open')) { if (e.key === 'Escape' && menu.classList.contains('open')) {
menu.classList.remove('open'); closeMobileNavMenu();
toggle.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
toggle.focus(); toggle.focus();
} }
}); });
document.addEventListener('click', (e) => { document.addEventListener('click', (e) => {
if (!menu.contains(e.target) && !toggle.contains(e.target)) { if (!menu.contains(e.target) && !toggle.contains(e.target)) {
menu.classList.remove('open'); closeMobileNavMenu();
toggle.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
} }
}); });
} }
@@ -80,18 +110,21 @@ function initMegaMenu() {
} }
function openMenu() { function openMenu() {
if (isMobileNav()) return;
cancelClose(); cancelClose();
productsItem.classList.add('open'); productsItem.classList.add('open');
trigger.setAttribute('aria-expanded', 'true'); trigger.setAttribute('aria-expanded', 'true');
} }
function beginClose() { function beginClose() {
if (isMobileNav()) return;
productsItem.classList.remove('open'); productsItem.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false'); trigger.setAttribute('aria-expanded', 'false');
megamenu.classList.add('is-closing'); megamenu.classList.add('is-closing');
} }
function scheduleClose(event) { function scheduleClose(event) {
if (isMobileNav()) return;
if (event && isPointerInMenu(event.relatedTarget)) return; if (event && isPointerInMenu(event.relatedTarget)) return;
clearTimeout(hideTimer); clearTimeout(hideTimer);
@@ -111,9 +144,21 @@ function initMegaMenu() {
megamenu.addEventListener('mouseenter', openMenu); megamenu.addEventListener('mouseenter', openMenu);
megamenu.addEventListener('mouseleave', scheduleClose); megamenu.addEventListener('mouseleave', scheduleClose);
trigger.addEventListener('click', (e) => {
if (!isMobileNav()) return;
e.preventDefault();
const isOpen = productsItem.classList.toggle('open');
trigger.setAttribute('aria-expanded', String(isOpen));
});
trigger.addEventListener('keydown', (e) => { trigger.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault(); e.preventDefault();
if (isMobileNav()) {
const isOpen = productsItem.classList.toggle('open');
trigger.setAttribute('aria-expanded', String(isOpen));
return;
}
const isOpen = productsItem.classList.toggle('open'); const isOpen = productsItem.classList.toggle('open');
if (isOpen) { if (isOpen) {
openMenu(); openMenu();
@@ -124,10 +169,27 @@ function initMegaMenu() {
trigger.setAttribute('aria-expanded', String(isOpen)); trigger.setAttribute('aria-expanded', String(isOpen));
} }
if (e.key === 'Escape') { if (e.key === 'Escape') {
if (isMobileNav()) {
productsItem.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false');
return;
}
cancelClose(); cancelClose();
beginClose(); beginClose();
} }
}); });
productsItem.querySelectorAll('.megamenu-product-item.has-subproducts').forEach((item) => {
const link = item.querySelector('.megamenu-product-link');
if (!link) return;
link.addEventListener('click', (e) => {
if (!isMobileNav()) return;
if (item.classList.contains('open')) return;
e.preventDefault();
item.classList.add('open');
});
});
} }
function initFAQAccordion() { function initFAQAccordion() {