fix(picker-column): fallback to elementFromPoint for iOS 16 Shadow DOM bug (#30479)

Issue number: resolves #29672

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

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?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- 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

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev build: `8.6.2-dev.11749761258.1b46b6a9`

---------

Co-authored-by: Vilhelm Josander <5067135+vilhelmjosander@users.noreply.github.com>
This commit is contained in:
Maria Hutt
2025-06-18 08:16:55 -07:00
committed by GitHub
parent 6811fe5cc8
commit 6ae2907742

View File

@ -376,7 +376,27 @@ export class PickerColumn implements ComponentInterface {
* elementsFromPoint can returns multiple elements * elementsFromPoint can returns multiple elements
* so find the relevant picker column option if one exists. * 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) { if (activeEl !== undefined) {
this.setPickerItemActiveState(activeEl, false); this.setPickerItemActiveState(activeEl, false);