From 12ef9345d6e5a9e7f60afb959b11807daaa2d3f1 Mon Sep 17 00:00:00 2001 From: ShaneK Date: Fri, 12 Dec 2025 08:03:54 -0800 Subject: [PATCH] fix(date-time): adding fallback for visibility back for e2e tests --- core/src/components/datetime/datetime.tsx | 85 ++++++++++++++--------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 4bd5d84f1d..e129b144d9 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -1105,6 +1105,26 @@ export class Datetime implements ComponentInterface { this.initializeKeyboardListeners(); } + /** + * FW-6931: Fallback check for when ResizeObserver doesn't fire reliably + * (e.g., WebKit during modal re-presentation). Called after element is + * hidden to catch when it becomes visible again. + */ + private checkVisibilityFallback = () => { + const { el } = this; + if (el.classList.contains('datetime-ready')) { + return; + } + + const rect = el.getBoundingClientRect(); + if (rect.width > 0 && rect.height > 0) { + this.initializeListeners(); + writeTask(() => { + el.classList.add('datetime-ready'); + }); + } + }; + componentDidLoad() { const { el } = this; @@ -1115,11 +1135,31 @@ export class Datetime implements ComponentInterface { * visible if used inside of a modal or a popover otherwise the scrollable * areas will not have the correct values snapped into place. * - * FW-6931: We use ResizeObserver to detect when the element transitions - * between having dimensions (visible) and zero dimensions (hidden). This - * is more reliable than IntersectionObserver for detecting visibility - * changes, especially when the element is inside a modal or popover. + * We use ResizeObserver to detect when the element transitions between + * having dimensions (visible) and zero dimensions (hidden). This is more + * reliable than IntersectionObserver for detecting visibility changes, + * especially when the element is inside a modal or popover. */ + const markReady = () => { + this.initializeListeners(); + writeTask(() => { + el.classList.add('datetime-ready'); + }); + }; + + const markHidden = () => { + this.destroyInteractionListeners(); + this.showMonthAndYear = false; + writeTask(() => { + el.classList.remove('datetime-ready'); + }); + /** + * Schedule fallback check for browsers where ResizeObserver + * doesn't fire reliably on re-presentation (e.g., WebKit). + */ + setTimeout(() => this.checkVisibilityFallback(), 100); + }; + if (typeof ResizeObserver !== 'undefined') { this.resizeObserver = new ResizeObserver((entries) => { const entry = entries[0]; @@ -1128,36 +1168,9 @@ export class Datetime implements ComponentInterface { const isReady = el.classList.contains('datetime-ready'); if (isVisible && !isReady) { - this.initializeListeners(); - - /** - * TODO FW-2793: Datetime needs a frame to ensure that it - * can properly scroll contents into view. As a result - * we hide the scrollable content until after that frame - * so users do not see the content quickly shifting. The downside - * is that the content will pop into view a frame after. Maybe there - * is a better way to handle this? - */ - writeTask(() => { - el.classList.add('datetime-ready'); - }); + markReady(); } else if (!isVisible && isReady) { - /** - * Clean up listeners when hidden so we can properly - * reinitialize scroll positions on re-presentation. - */ - this.destroyInteractionListeners(); - - /** - * Close month/year picker when hidden, otherwise - * it will be open when re-presented with a 0-height - * scroll area, showing the wrong month. - */ - this.showMonthAndYear = false; - - writeTask(() => { - el.classList.remove('datetime-ready'); - }); + markHidden(); } }); @@ -1166,6 +1179,12 @@ export class Datetime implements ComponentInterface { * its display animation starting (such as when shown in a modal). */ raf(() => this.resizeObserver?.observe(el)); + + /** + * Fallback for initial presentation in case ResizeObserver + * doesn't fire reliably (e.g., WebKit). + */ + setTimeout(() => this.checkVisibilityFallback(), 100); } else { /** * Fallback for test environments where ResizeObserver is not available.