fix: responsive mega menu
This commit is contained in:
+68
-6
@@ -12,6 +12,12 @@ const SELECTORS = {
|
||||
citationCopy: '.citation-copy',
|
||||
};
|
||||
|
||||
const MOBILE_NAV_MQ = window.matchMedia('(max-width: 768px)');
|
||||
|
||||
function isMobileNav() {
|
||||
return MOBILE_NAV_MQ.matches;
|
||||
}
|
||||
|
||||
function initNavbarScroll() {
|
||||
const navbar = document.querySelector(SELECTORS.navbar);
|
||||
if (!navbar) return;
|
||||
@@ -28,6 +34,26 @@ function initNavbarScroll() {
|
||||
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() {
|
||||
const toggle = document.querySelector(SELECTORS.navbarToggle);
|
||||
const menu = document.querySelector(SELECTORS.navbarMenu);
|
||||
@@ -37,22 +63,26 @@ function initMobileMenu() {
|
||||
const isOpen = menu.classList.toggle('open');
|
||||
toggle.classList.toggle('open', 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) => {
|
||||
if (e.key === 'Escape' && menu.classList.contains('open')) {
|
||||
menu.classList.remove('open');
|
||||
toggle.classList.remove('open');
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
closeMobileNavMenu();
|
||||
toggle.focus();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!menu.contains(e.target) && !toggle.contains(e.target)) {
|
||||
menu.classList.remove('open');
|
||||
toggle.classList.remove('open');
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
closeMobileNavMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -80,18 +110,21 @@ function initMegaMenu() {
|
||||
}
|
||||
|
||||
function openMenu() {
|
||||
if (isMobileNav()) return;
|
||||
cancelClose();
|
||||
productsItem.classList.add('open');
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
|
||||
function beginClose() {
|
||||
if (isMobileNav()) return;
|
||||
productsItem.classList.remove('open');
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
megamenu.classList.add('is-closing');
|
||||
}
|
||||
|
||||
function scheduleClose(event) {
|
||||
if (isMobileNav()) return;
|
||||
if (event && isPointerInMenu(event.relatedTarget)) return;
|
||||
|
||||
clearTimeout(hideTimer);
|
||||
@@ -111,9 +144,21 @@ function initMegaMenu() {
|
||||
megamenu.addEventListener('mouseenter', openMenu);
|
||||
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) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
if (isMobileNav()) {
|
||||
const isOpen = productsItem.classList.toggle('open');
|
||||
trigger.setAttribute('aria-expanded', String(isOpen));
|
||||
return;
|
||||
}
|
||||
const isOpen = productsItem.classList.toggle('open');
|
||||
if (isOpen) {
|
||||
openMenu();
|
||||
@@ -124,10 +169,27 @@ function initMegaMenu() {
|
||||
trigger.setAttribute('aria-expanded', String(isOpen));
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
if (isMobileNav()) {
|
||||
productsItem.classList.remove('open');
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
return;
|
||||
}
|
||||
cancelClose();
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user