From 6ae29077424434f3523d75426f3328765a4797f4 Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Wed, 18 Jun 2025 08:16:55 -0700 Subject: [PATCH] fix(picker-column): fallback to elementFromPoint for iOS 16 Shadow DOM bug (#30479) Issue number: resolves #29672 --------- ## What is the current behavior? The issue on iOS 16 with `elementsFromPoint` is related to how it handles Shadow DOM retargeting when called from the document (global) context. It leads to an `undefined` element that is required to trigger `ionChange`. ## What is the new behavior? - Returns the top most element as a fallback only if the element has a tag of `'ion-picker-column-option'`. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `8.6.2-dev.11749761258.1b46b6a9` --------- Co-authored-by: Vilhelm Josander <5067135+vilhelmjosander@users.noreply.github.com> --- .../picker-column/picker-column.tsx | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/core/src/components/picker-column/picker-column.tsx b/core/src/components/picker-column/picker-column.tsx index 0b4f57dd8a..3393cadf6e 100644 --- a/core/src/components/picker-column/picker-column.tsx +++ b/core/src/components/picker-column/picker-column.tsx @@ -376,7 +376,27 @@ export class PickerColumn implements ComponentInterface { * elementsFromPoint can returns multiple elements * so find the relevant picker column option if one exists. */ - const newActiveElement = elementsAtPoint.find((el) => el.tagName === 'ION-PICKER-COLUMN-OPTION'); + let newActiveElement = elementsAtPoint.find((el) => el.tagName === 'ION-PICKER-COLUMN-OPTION'); + + /** + * TODO(FW-6594): Remove this workaround when iOS 16 is no longer + * supported. + * + * If `elementsFromPoint` failed to find the active element (a known + * issue on iOS 16 when elements are in a Shadow DOM and the + * referenceNode is the document), a fallback to `elementFromPoint` + * is used. While `elementsFromPoint` returns all elements, + * `elementFromPoint` returns only the top-most, which is sufficient + * for this use case and appears to handle Shadow DOM retargeting + * more reliably in this specific iOS bug. + */ + if (newActiveElement === undefined) { + const fallbackActiveElement = referenceNode.elementFromPoint(centerX, centerY); + + if (fallbackActiveElement?.tagName === 'ION-PICKER-COLUMN-OPTION') { + newActiveElement = fallbackActiveElement as HTMLIonPickerColumnOptionElement; + } + } if (activeEl !== undefined) { this.setPickerItemActiveState(activeEl, false);