Skip to content

Commit

Permalink
MWPW-163916 [Mobile GNAV] | Flickering issue while scrolling when LNA…
Browse files Browse the repository at this point in the history
…V is opened (#3419)

* Add overflow hidden to html if the body has it for iOS safari

* Added position fixed to disable scroll for ios safari

* use position: relative instead of fixed

* undo previous changes

* removed position absolute from the feds localnav curtain

* removed the different height when the localnav curtain is active

* trying position: absolute f=to prevent scrolling on iOS

* add overflow hidden to html tag as when the body has it

* Undo previous change

* Used event.preventDefault on a scroll event on the window to prevent scrolling in iOS

* tried event.preventDefault to stop body from scrolling on iOS Safari

* Set the scroll to the current number on scroll when scroll is disabled

* Change scroll to touchmove

* iOS safari defaults event listener passive to true

* Small refactor

* disabled scroll for the non localnav mobile gnav as well

* remove scroll on body instead of window

* Disable body scroll when local nav or mobile menu is open

* corrected the import

* fixed a typo

* Use position fixed to prevent scrolling in iOS

* eslint

* more eslint problems

* Fixed an issue where swtiching from mobile to desktop made the dekstop mega menu popup have the wrong position

* gave ios-disable-scroll the correct behavior for non localnavs as well

* Fixed a couple of bugs

* fixed an issue where firefox treats position fixed as position absolute
  • Loading branch information
sharmrj authored Jan 7, 2025
1 parent 34d9209 commit 6b25364
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 13 deletions.
15 changes: 8 additions & 7 deletions libs/blocks/global-navigation/global-navigation.css
Original file line number Diff line number Diff line change
Expand Up @@ -1189,16 +1189,10 @@ header.new-nav .feds-breadcrumbs li:first-child:not(:nth-last-child(-n+3)):after

.feds-localnav.feds-localnav--active .feds-localnav-curtain {
width: 100%;
height: calc(101lvh - (var(--feds-height-nav) + var(--feds-localnav-height)));
height: 101lvh;
padding-bottom: env(safe-area-inset-bottom);
position: absolute;
background: var(--feds-color-black-v2);
opacity: 0.7;
top: var(--feds-localnav-height);
}

.feds-localnav.feds-localnav--active.is-sticky .feds-localnav-curtain {
height: calc(100dvh - var(--feds-localnav-height));
}

.feds-localnav.feds-localnav--active .feds-localnav-exit {
Expand Down Expand Up @@ -1267,3 +1261,10 @@ header.new-nav .feds-breadcrumbs li:first-child:not(:nth-last-child(-n+3)):after
opacity: 0;
}
}

/* */

.disable-ios-scroll {
overflow: hidden;
position: fixed;
}
35 changes: 31 additions & 4 deletions libs/blocks/global-navigation/global-navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {
animateInSequence,
transformTemplateToMobile,
closeAllTabs,
disableMobileScroll,
enableMobileScroll,
} from './utilities/utilities.js';
import { getFedsPlaceholderConfig } from '../../utils/federated.js';

Expand Down Expand Up @@ -325,9 +327,16 @@ class Gnav {
// Order is important, decorateTopnavWrapper will render the nav
// Ensure any critical task is executed before it
const tasks = [
// decorateAside is the only async function that fires prior to rendering
// (at time of writing). If there is no aside it returns sync -- no problem.
// But if there is, we need those functions (import + decorate) to enter the event loop
// before the delayed decorateDropdown function does.
// the rest is taken care of by the 'await' semantics
// We needn't worry about delays now since decorateAside
// needed to run anyway prior to decorateTopNavWrapper
this.decorateAside,
this.decorateMainNav,
this.decorateTopNav,
this.decorateAside,
this.decorateTopnavWrapper,
loadBaseStyles,
this.ims,
Expand All @@ -340,7 +349,7 @@ class Gnav {
this.block.addEventListener('keydown', fetchKeyboardNav);
setTimeout(this.loadDelayed, CONFIG.delays.loadDelayed);
setTimeout(fetchKeyboardNav, CONFIG.delays.keyboardNav);
for await (const task of tasks) {
for (const task of tasks) {
await yieldToMain();
await task();
}
Expand Down Expand Up @@ -387,7 +396,10 @@ class Gnav {
const [title, navTitle = ''] = this.getOriginalTitle(firstElem);
let localNav = document.querySelector('.feds-localnav');
if (!localNav) {
lanaLog({ message: 'GNAV: Localnav does not include \'localnav\' in its name.', tags: 'errorType=info,module=gnav' });
lanaLog({
message: 'GNAV: Localnav does not include \'localnav\' in its name.',
tags: 'errorType=info,module=gnav',
});
localNav = toFragment`<div class="feds-localnav"/>`;
this.block.after(localNav);
}
Expand Down Expand Up @@ -415,11 +427,14 @@ class Gnav {
const isActive = localNav.classList.contains('feds-localnav--active');
localNav.querySelector('.feds-localnav-title').setAttribute('aria-expanded', isActive);
localNav.querySelector('.feds-localnav-title').setAttribute('daa-ll', `${title}_localNav|${isActive ? 'close' : 'open'}`);
if (isActive) disableMobileScroll();
else enableMobileScroll();
});

localNav.querySelector('.feds-localnav-curtain').addEventListener('click', (e) => {
trigger({ element: e.currentTarget, event: e, type: 'localNav-curtain' });
document.body.classList.remove('disable-scroll');
enableMobileScroll();
});
this.elements.localNav = localNav;
localNavItems[0].querySelector('a').textContent = title.trim();
Expand Down Expand Up @@ -774,12 +789,15 @@ class Gnav {
const toggle = this.elements.mobileToggle;
const isExpanded = this.isToggleExpanded();
if (!isExpanded && this.newMobileNav) {
disableMobileScroll();
const sections = document.querySelectorAll('header.new-nav .feds-nav > section.feds-navItem > button.feds-navLink');
animateInSequence(sections, 0.075);
if (this.isLocalNav()) {
const section = sections[0];
queueMicrotask(() => section.click());
}
} else if (isExpanded && this.newMobileNav) {
enableMobileScroll();
}
toggle?.setAttribute('aria-expanded', !isExpanded);
document.body.classList.toggle('disable-scroll', !isExpanded);
Expand Down Expand Up @@ -1079,6 +1097,7 @@ class Gnav {
popup.querySelector('.close-icon')?.addEventListener('click', this.toggleMenuMobile);
}
isDesktop.addEventListener('change', async () => {
enableMobileScroll();
if (isDesktop.matches) {
popup.innerHTML = originalContent;
this.block.classList.remove('new-nav');
Expand Down Expand Up @@ -1124,8 +1143,16 @@ class Gnav {
dropdownTrigger.addEventListener('click', (e) => {
if (!isDesktop.matches && this.newMobileNav && isSectionMenu) {
const popup = dropdownTrigger.nextElementSibling;
if (popup) popup.style = `top: calc(${window.scrollY}px - var(--feds-height-nav) - 1px)`;
// document.body.style.top should always be set
// at this point by calling disableMobileScroll
if (popup && this.isLocalNav()) {
const y = Math.abs(parseInt(document.body.style.top, 10));
popup.style = `top: calc(${y || 0}px - var(--feds-height-nav))`;
}
makeTabActive(popup);
} else if (isDesktop.matches && this.newMobileNav && isSectionMenu) {
const popup = dropdownTrigger.nextElementSibling;
if (popup) popup.style.removeProperty('top');
}
trigger({ element: dropdownTrigger, event: e });
setActiveDropdown(dropdownTrigger);
Expand Down
22 changes: 20 additions & 2 deletions libs/blocks/global-navigation/utilities/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import { getFederatedContentRoot, getFederatedUrl, getFedsPlaceholderConfig } from '../../../utils/federated.js';
import { processTrackingLabels } from '../../../martech/attributes.js';
import { replaceText } from '../../../features/placeholders.js';
import { PERSONALIZATION_TAGS } from '../../../features/personalization/personalization.js';

loadLana();

Expand Down Expand Up @@ -413,6 +414,22 @@ export const closeAllTabs = (tabs, tabpanels) => {
tabs.forEach((t) => t.setAttribute('aria-selected', 'false'));
};

export const disableMobileScroll = () => {
if (!PERSONALIZATION_TAGS.safari()) return;
document.body.style.top = `-${window.scrollY}px`;
document.body.classList.add('disable-ios-scroll');
};

export const enableMobileScroll = () => {
if (!PERSONALIZATION_TAGS.safari()) return;
if (!document.body.style.top) return;
const y = Math.abs(parseInt(document.body.style.top, 10));
if (Number.isNaN(y)) return;
document.body.classList.remove('disable-ios-scroll');
document.body.style.removeProperty('top');
window.scroll(0, y || 0);
};

export const transformTemplateToMobile = async (popup, item, localnav = false) => {
const notMegaMenu = popup.parentElement.tagName === 'DIV';
const originalContent = popup.innerHTML;
Expand Down Expand Up @@ -483,13 +500,14 @@ export const transformTemplateToMobile = async (popup, item, localnav = false) =
popup.querySelector('.close-icon')?.addEventListener('click', () => {
document.querySelector(selectors.mainNavToggle).focus();
closeAllDropdowns();
enableMobileScroll();
});
popup.querySelector('.main-menu')?.addEventListener('click', (e) => {
e.target.closest(selectors.activeDropdown).querySelector('button').focus();
closeAllDropdowns();
});
const tabbuttons = popup.querySelectorAll('.global-navigation .tabs button');
const tabpanels = popup.querySelectorAll('.global-navigation .tab-content [role="tabpanel"]');
const tabbuttons = popup.querySelectorAll('.tabs button');
const tabpanels = popup.querySelectorAll('.tab-content [role="tabpanel"]');

tabpanels.forEach((panel) => {
animateInSequence(panel.querySelectorAll('a'), 0.02);
Expand Down

0 comments on commit 6b25364

Please sign in to comment.