From e86c0ce6c91ba4a708aa374e3e95d13bbcd81ca8 Mon Sep 17 00:00:00 2001 From: Bandana Laishram Date: Mon, 11 Nov 2024 14:49:55 +0530 Subject: [PATCH] Localnav design and event listeners (#3164) * Localnav design and event listeners * Lint fix * Adding Overview title support --- .../global-navigation/global-navigation.css | 57 +++++++++++--- .../global-navigation/global-navigation.js | 77 +++++++++++++++---- .../global-navigation/utilities/utilities.js | 13 +++- 3 files changed, 118 insertions(+), 29 deletions(-) diff --git a/libs/blocks/global-navigation/global-navigation.css b/libs/blocks/global-navigation/global-navigation.css index b74bead49e..aaee255a65 100644 --- a/libs/blocks/global-navigation/global-navigation.css +++ b/libs/blocks/global-navigation/global-navigation.css @@ -987,28 +987,28 @@ header + .feds-localnav { display: block; top: 0; width: 100%; - background: #fff; left: 0; z-index: 2; } .feds-localnav-title { width: 100%; - height: 80px; - font-size: 22px; - font-weight: 600; + height: 53px; + font-size: 16px; + font-weight: 700; border: 0; - padding: 12px; + padding: 0 20px; text-align: justify; border-top: 1px solid #eee; border-bottom: 1px solid #eee; - background-color: #fff; + background-color: #F8F8F8; } .feds-localnav-items { - background-color: #fff; + background: #F3F3F3; border-bottom: 1px solid #eee; display: none; + box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); } .feds-localnav-items .feds-navLink { @@ -1017,14 +1017,53 @@ header + .feds-localnav { .feds-localnav.active .feds-localnav-items { display: block; + width: 100%; + position: absolute; } -.feds-localnav .feds-localnav-items .feds-navLink { +.feds-localnav.active .feds-localnav-items .feds-menu-items { + padding: 0; border-bottom: 0; - font-size: 16px; +} + +.feds-localnav.active .feds-localnav-items .feds-menu-column > ul { + padding: 0; +} + +.feds-localnav.active .feds-localnav-items .feds-menu-column > ul .feds-navLink { + padding-left: 38px; +} + +.feds-localnav.active .feds-localnav-items .feds-menu-items .feds-navLink { + padding: 12px 56px; +} + +.feds-localnav .feds-navLink[aria-expanded="true"] { font-weight: 600; } +.feds-localnav .feds-localnav-items .feds-navLink { + border-bottom: 0; + font-size: 14px; + padding: 12px 20px; + background: #F3F3F3; +} + +.feds-localnav .feds-localnav-items .feds-menu-headline { + background: #F3F3F3; + font-weight: 400; + border-bottom: 0; + padding: 12px 38px; +} + +.feds-localnav .feds-localnav-items .feds-navItem--centered { + padding: 12px 20px; +} + +.feds-localnav .feds-dropdown--active::before { + display: none; +} + .feds-localnav.active .feds-localnav-title::after { transform: rotateZ(-135deg); } diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js index 6592103145..bdeecf2c88 100644 --- a/libs/blocks/global-navigation/global-navigation.js +++ b/libs/blocks/global-navigation/global-navigation.js @@ -375,23 +375,36 @@ class Gnav { }; decorateLocalNav = () => { - if (!newNavEnabled || !this.isLocalNav()) return; - const localNav = toFragment`
`; - const localNavitems = this.elements.navWrapper.querySelector('.feds-nav').querySelectorAll('.feds-navItem:not(.feds-navItem--section)'); - const itemWrapper = localNav.querySelector('.feds-localnav-items'); - localNavitems.forEach((elem, idx) => { - if (idx === 0) { - localNav.querySelector('.feds-localnav-title').innerText = elem.textContent.trim(); - return; - } - itemWrapper.appendChild(elem.cloneNode(true)); - }); - localNav.querySelector('.feds-localnav-title').addEventListener('click', () => { - if (localNav.classList.contains('active')) localNav.classList.remove('active'); - else localNav.classList.add('active'); - }); - this.elements.localNav = localNav; - this.block.after(localNav); + const localNavItems = this.elements.navWrapper.querySelector('.feds-nav').querySelectorAll('.feds-navItem:not(.feds-navItem--section)'); + const [title, navTitle = ''] = localNavItems[0].querySelector('a').textContent.split('|'); + if (this.elements.localNav || !newNavEnabled || !this.isLocalNav() || isDesktop.matches) { + localNavItems[0].querySelector('a').textContent = title.trim(); + } else { + const localNav = toFragment` +
+ +
+
`; + + const itemWrapper = localNav.querySelector('.feds-localnav-items'); + localNavItems.forEach((elem, idx) => { + const clonedItem = elem.cloneNode(true); + const link = clonedItem.querySelector('a'); + + if (idx === 0) { + localNav.querySelector('.feds-localnav-title').innerText = title.trim(); + link.textContent = navTitle.trim() || title.trim(); + } + + itemWrapper.appendChild(clonedItem); + }); + + localNav.querySelector('.feds-localnav-title').addEventListener('click', () => { + localNav.classList.toggle('active'); + }); + this.elements.localNav = localNav; + this.block.after(localNav); + } }; decorateTopnavWrapper = async () => { @@ -407,6 +420,7 @@ class Gnav { this.elements.aside, this.elements.topnavWrapper, ); + this.decorateLocalNav(); }; @@ -438,6 +452,7 @@ class Gnav { this.elements.navWrapper.prepend(this.elements.breadcrumbsWrapper); } } + this.decorateLocalNav(); }); // Add a modifier when the nav is tangent to the viewport and content is partly hidden @@ -956,6 +971,29 @@ class Gnav { } }; + // Copying dropdown contents to localNav items + const decorateLocalNavItems = (navItem, template) => { + const elements = [...document.querySelectorAll('.feds-localnav .feds-navItem')].find( + (el) => el.textContent.trim() === navItem.textContent, + ); + if (elements) { + elements.innerHTML = template.innerHTML; + // Reattach click events, as cloned elem don't retain event listeners + elements.querySelector('button')?.addEventListener('click', (e) => { + trigger({ element: e.currentTarget, event: e, type: 'localNavTitle' }); + setActiveDropdown(e.currentTarget); + }); + + elements.querySelectorAll('.feds-menu-headline').forEach((elem) => { + // Reattach click event listener to headlines + elem?.addEventListener('click', (e) => { + trigger({ element: e.currentTarget, event: e, type: 'headline' }); + setActiveDropdown(e.currentTarget); + }); + }); + } + }; + // All dropdown decoration is delayed const delayDropdownDecoration = ({ template } = {}) => { let decorationTimeout; @@ -971,6 +1009,11 @@ class Gnav { template, type: itemType, }); + + if (this.isLocalNav() && newNavEnabled) { + decorateLocalNavItems(item, template); + } + const popup = template.querySelector('.feds-popup'); let originalContent = popup.innerHTML; diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js index 3f20380181..f9bd04ec4c 100644 --- a/libs/blocks/global-navigation/utilities/utilities.js +++ b/libs/blocks/global-navigation/utilities/utilities.js @@ -10,6 +10,11 @@ loadLana(); const FEDERAL_PATH_KEY = 'federal'; +const selectorMap = { + headline: '.feds-menu-headline[aria-expanded="true"]', + localNavTitle: '.feds-navLink[aria-expanded="true"]', +}; + export const selectors = { globalNav: '.global-navigation', curtain: '.feds-curtain', @@ -282,9 +287,8 @@ export const [hasActiveLink, setActiveLink, isActiveLink, getActiveLink] = (() = })(); export function closeAllDropdowns({ type } = {}) { - const selector = type === 'headline' - ? '.feds-menu-headline[aria-expanded="true"]' - : `${selectors.globalNav} [aria-expanded='true']`; + const selector = selectorMap[type] || `${selectors.globalNav} [aria-expanded='true']`; + const openElements = document.querySelectorAll(selector); if (!openElements) return; [...openElements].forEach((el) => { @@ -394,6 +398,9 @@ export const [setUserProfile, getUserProfile] = (() => { })(); export const transformTemplateToMobile = async (popup, item, localnav = false) => { + const notMegaMenu = popup.parentElement.tagName === 'DIV'; + if (notMegaMenu) return; + const originalContent = popup.innerHTML; const tabs = [...popup.querySelectorAll('.feds-menu-section')] .filter((section) => !section.querySelector('.feds-promo') && section.textContent)