From 3c03b9ba9526642a45ed1878c0a06f5b2fdd9320 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Wed, 3 Dec 2025 10:13:02 +0000 Subject: [PATCH 1/8] add intersection fix --- core/src/components/datetime/datetime.tsx | 40 +++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 71b08a33098..e04ec968245 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -124,6 +124,14 @@ export class Datetime implements ComponentInterface { private destroyCalendarListener?: () => void; private destroyKeyboardMO?: () => void; + /** + * Tracks the current visibility state of the datetime component. + * This prevents race conditions when the datetime rapidly becomes visible/hidden + * (e.g., when dragging a modal on iOS), ensuring the datetime-ready class + * accurately reflects the component's current intersection state. + */ + private isIntersecting = false; + // TODO(FW-2832): types (DatetimeParts causes some errors that need untangling) private minParts?: any; private maxParts?: any; @@ -1148,6 +1156,13 @@ export class Datetime implements ComponentInterface { return; } + /** + * Track that the component is now intersecting. + * This prevents stale writeTask operations from incorrectly + * removing the datetime-ready class. + */ + this.isIntersecting = true; + this.initializeListeners(); /** @@ -1159,7 +1174,14 @@ export class Datetime implements ComponentInterface { * is a better way to handle this? */ writeTask(() => { - this.el.classList.add('datetime-ready'); + /** + * Only add the class if the component is still intersecting. + * This prevents race conditions when the visibility state changes + * rapidly (e.g., when dragging a modal on iOS). + */ + if (this.isIntersecting) { + this.el.classList.add('datetime-ready'); + } }); }; const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01, root: el }); @@ -1197,6 +1219,13 @@ export class Datetime implements ComponentInterface { return; } + /** + * Track that the component is no longer intersecting. + * This prevents stale writeTask operations from incorrectly + * adding the datetime-ready class. + */ + this.isIntersecting = false; + this.destroyInteractionListeners(); /** @@ -1209,7 +1238,14 @@ export class Datetime implements ComponentInterface { this.showMonthAndYear = false; writeTask(() => { - this.el.classList.remove('datetime-ready'); + /** + * Only remove the class if the component is still not intersecting. + * This prevents race conditions when the visibility state changes + * rapidly (e.g., when dragging a modal on iOS). + */ + if (!this.isIntersecting) { + this.el.classList.remove('datetime-ready'); + } }); }; const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0, root: el }); From ce7280b5def2f71ccde6561b0886ac57a4e4e38a Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Wed, 3 Dec 2025 10:18:50 +0000 Subject: [PATCH 2/8] fix theme issue --- core/src/components/datetime/utils/data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/components/datetime/utils/data.ts b/core/src/components/datetime/utils/data.ts index 79323cd534f..cc50f4d512b 100644 --- a/core/src/components/datetime/utils/data.ts +++ b/core/src/components/datetime/utils/data.ts @@ -1,4 +1,4 @@ -import type { Theme } from '../../../interface'; +import type { Mode, Theme } from '../../../interface'; import type { DatetimeParts, DatetimeHourCycle } from '../datetime-interface'; import { isAfter, isBefore, isSameDay } from './comparison'; @@ -70,7 +70,7 @@ const hour24 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1 * MD should display days such as "M" * or "T". */ -export const getDaysOfWeek = (locale: string, theme: Theme, firstDayOfWeek = 0) => { +export const getDaysOfWeek = (locale: string, theme: Theme | Mode, firstDayOfWeek = 0) => { /** * Nov 1st, 2020 starts on a Sunday. * ion-datetime assumes weeks start on Sunday, From 39ce144174a09e848f951a96bb6f01da81ed3866 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Thu, 4 Dec 2025 14:32:25 +0000 Subject: [PATCH 3/8] Revert "add intersection fix" This reverts commit 3c03b9ba9526642a45ed1878c0a06f5b2fdd9320. --- core/src/components/datetime/datetime.tsx | 40 ++--------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index e04ec968245..71b08a33098 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -124,14 +124,6 @@ export class Datetime implements ComponentInterface { private destroyCalendarListener?: () => void; private destroyKeyboardMO?: () => void; - /** - * Tracks the current visibility state of the datetime component. - * This prevents race conditions when the datetime rapidly becomes visible/hidden - * (e.g., when dragging a modal on iOS), ensuring the datetime-ready class - * accurately reflects the component's current intersection state. - */ - private isIntersecting = false; - // TODO(FW-2832): types (DatetimeParts causes some errors that need untangling) private minParts?: any; private maxParts?: any; @@ -1156,13 +1148,6 @@ export class Datetime implements ComponentInterface { return; } - /** - * Track that the component is now intersecting. - * This prevents stale writeTask operations from incorrectly - * removing the datetime-ready class. - */ - this.isIntersecting = true; - this.initializeListeners(); /** @@ -1174,14 +1159,7 @@ export class Datetime implements ComponentInterface { * is a better way to handle this? */ writeTask(() => { - /** - * Only add the class if the component is still intersecting. - * This prevents race conditions when the visibility state changes - * rapidly (e.g., when dragging a modal on iOS). - */ - if (this.isIntersecting) { - this.el.classList.add('datetime-ready'); - } + this.el.classList.add('datetime-ready'); }); }; const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01, root: el }); @@ -1219,13 +1197,6 @@ export class Datetime implements ComponentInterface { return; } - /** - * Track that the component is no longer intersecting. - * This prevents stale writeTask operations from incorrectly - * adding the datetime-ready class. - */ - this.isIntersecting = false; - this.destroyInteractionListeners(); /** @@ -1238,14 +1209,7 @@ export class Datetime implements ComponentInterface { this.showMonthAndYear = false; writeTask(() => { - /** - * Only remove the class if the component is still not intersecting. - * This prevents race conditions when the visibility state changes - * rapidly (e.g., when dragging a modal on iOS). - */ - if (!this.isIntersecting) { - this.el.classList.remove('datetime-ready'); - } + this.el.classList.remove('datetime-ready'); }); }; const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0, root: el }); From 324ae265170a7d79f2d86b66156c8424e75f9b35 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Fri, 5 Dec 2025 11:28:34 +0000 Subject: [PATCH 4/8] add datetime new variable to control opacity on ionic theme --- .../components/datetime/datetime.common.scss | 12 +----------- .../components/datetime/datetime.ionic.scss | 18 ++++++++++++++++++ .../components/datetime/datetime.native.scss | 10 ++++++++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/core/src/components/datetime/datetime.common.scss b/core/src/components/datetime/datetime.common.scss index a7532c41420..5b11b59b9df 100644 --- a/core/src/components/datetime/datetime.common.scss +++ b/core/src/components/datetime/datetime.common.scss @@ -25,26 +25,16 @@ width: 100%; } -:host .calendar-body, -:host .datetime-year { - opacity: 0; -} - :host(:not(.datetime-ready)) .datetime-year { position: absolute; pointer-events: none; } -:host(.datetime-ready) .calendar-body { - opacity: 1; -} - :host(.datetime-ready) .datetime-year { display: none; - - opacity: 1; } + /** * Changing the physical order of the * picker columns in the DOM is added diff --git a/core/src/components/datetime/datetime.ionic.scss b/core/src/components/datetime/datetime.ionic.scss index 82f447f1a54..c565fc5b47e 100644 --- a/core/src/components/datetime/datetime.ionic.scss +++ b/core/src/components/datetime/datetime.ionic.scss @@ -12,6 +12,24 @@ --background: #{globals.$ion-bg-surface-default}; --focus-ring-color: #{globals.$ion-border-focus-default}; --focus-ring-width: #{globals.$ion-border-radius-025}; + --body-opacity: 0; + --year-opacity: 0; +} + +:host .calendar-body { + opacity: var(--body-opacity); +} + +:host .datetime-year { + opacity: var(--year-opacity); +} + +:host(.datetime-ready) .calendar-body { + --body-opacity: 1; +} + +:host(.datetime-ready) .datetime-year { + --year-opacity: 1; } // Header diff --git a/core/src/components/datetime/datetime.native.scss b/core/src/components/datetime/datetime.native.scss index eee452f1076..9c6e562e2d1 100644 --- a/core/src/components/datetime/datetime.native.scss +++ b/core/src/components/datetime/datetime.native.scss @@ -23,6 +23,16 @@ max-width: 350px; } +:host .calendar-body, +:host .datetime-year { + opacity: 0; +} + +:host(.datetime-ready) .calendar-body, +:host(.datetime-ready) .datetime-year { + opacity: 1; +} + /** * This ensures that the picker is appropriately * sized and never truncates the text. From b947bd5f8c90ebaad0d45d6de8a6c3cf5fcbaf64 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Fri, 5 Dec 2025 11:40:37 +0000 Subject: [PATCH 5/8] reverted type fix --- core/src/components/datetime/utils/data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/components/datetime/utils/data.ts b/core/src/components/datetime/utils/data.ts index cc50f4d512b..79323cd534f 100644 --- a/core/src/components/datetime/utils/data.ts +++ b/core/src/components/datetime/utils/data.ts @@ -1,4 +1,4 @@ -import type { Mode, Theme } from '../../../interface'; +import type { Theme } from '../../../interface'; import type { DatetimeParts, DatetimeHourCycle } from '../datetime-interface'; import { isAfter, isBefore, isSameDay } from './comparison'; @@ -70,7 +70,7 @@ const hour24 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1 * MD should display days such as "M" * or "T". */ -export const getDaysOfWeek = (locale: string, theme: Theme | Mode, firstDayOfWeek = 0) => { +export const getDaysOfWeek = (locale: string, theme: Theme, firstDayOfWeek = 0) => { /** * Nov 1st, 2020 starts on a Sunday. * ion-datetime assumes weeks start on Sunday, From 098a56d6cc9bf59e0308d0f610cfe330a9949163 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Fri, 5 Dec 2025 11:40:43 +0000 Subject: [PATCH 6/8] added TODO info --- core/src/components/datetime/datetime.ionic.scss | 6 ++++++ core/src/components/datetime/datetime.native.scss | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/core/src/components/datetime/datetime.ionic.scss b/core/src/components/datetime/datetime.ionic.scss index c565fc5b47e..1de6dc5c440 100644 --- a/core/src/components/datetime/datetime.ionic.scss +++ b/core/src/components/datetime/datetime.ionic.scss @@ -12,10 +12,16 @@ --background: #{globals.$ion-bg-surface-default}; --focus-ring-color: #{globals.$ion-border-focus-default}; --focus-ring-width: #{globals.$ion-border-radius-025}; + /** + * TODO(FW-6931): Remove these variables upon solving the root cause + */ --body-opacity: 0; --year-opacity: 0; } + /** + * TODO(FW-6931): Remove all this css related to opacity upon solving the root cause + */ :host .calendar-body { opacity: var(--body-opacity); } diff --git a/core/src/components/datetime/datetime.native.scss b/core/src/components/datetime/datetime.native.scss index 9c6e562e2d1..e000e207057 100644 --- a/core/src/components/datetime/datetime.native.scss +++ b/core/src/components/datetime/datetime.native.scss @@ -23,11 +23,17 @@ max-width: 350px; } +/** + * TODO(FW-6931): Move this back to common file upon solving the root cause + */ :host .calendar-body, :host .datetime-year { opacity: 0; } +/** + * TODO(FW-6931): Move this back to common file upon solving the root cause + */ :host(.datetime-ready) .calendar-body, :host(.datetime-ready) .datetime-year { opacity: 1; From e406c7f335243766c02a97d305fc9228e91142ef Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Fri, 5 Dec 2025 11:48:29 +0000 Subject: [PATCH 7/8] fix header border token --- core/src/components/header/header.ionic.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/components/header/header.ionic.scss b/core/src/components/header/header.ionic.scss index 0a216726a77..75911184988 100644 --- a/core/src/components/header/header.ionic.scss +++ b/core/src/components/header/header.ionic.scss @@ -8,7 +8,7 @@ ion-header { z-index: 10; // TODO(ROU-10853): replace this value with a layer token. &.header-divider { - border-bottom: globals.$ion-border-size-025 globals.$ion-border-style-solid globals.$ion-primitives-neutral-300; + border-bottom: globals.$ion-border-size-025 globals.$ion-border-style-solid globals.$ion-border-default; } } From 2e7b7e0f43055ffd1f681a7c5d4691139d9417a0 Mon Sep 17 00:00:00 2001 From: BenOsodrac Date: Fri, 5 Dec 2025 11:48:34 +0000 Subject: [PATCH 8/8] fix lint --- core/src/components/datetime/datetime.common.scss | 1 - core/src/components/datetime/datetime.ionic.scss | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/components/datetime/datetime.common.scss b/core/src/components/datetime/datetime.common.scss index 5b11b59b9df..97730fa9eb6 100644 --- a/core/src/components/datetime/datetime.common.scss +++ b/core/src/components/datetime/datetime.common.scss @@ -34,7 +34,6 @@ display: none; } - /** * Changing the physical order of the * picker columns in the DOM is added diff --git a/core/src/components/datetime/datetime.ionic.scss b/core/src/components/datetime/datetime.ionic.scss index 1de6dc5c440..e1411eacb8b 100644 --- a/core/src/components/datetime/datetime.ionic.scss +++ b/core/src/components/datetime/datetime.ionic.scss @@ -19,7 +19,7 @@ --year-opacity: 0; } - /** +/** * TODO(FW-6931): Remove all this css related to opacity upon solving the root cause */ :host .calendar-body {