From 03e8be2657c8aa81d2464f5d65ab090ce8a82788 Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <48283236+raphaelbernhart@users.noreply.github.com> Date: Fri, 21 Jun 2024 01:34:43 +0200 Subject: [PATCH] fix(components): fix iOS select click event listening (#16393) iOS Safari does not handle click events when a mouseenter event is registered and a DOM-change happens in a child. We use a Vue custom event binding to only register the event on non-iOS devices. The inputHovering state gets updated now on iOS-devices on click. This is needed as the mouseenter event normally does this. closed #5210 --- packages/components/select/src/select.vue | 2 +- packages/components/select/src/useSelect.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/components/select/src/select.vue b/packages/components/select/src/select.vue index 490efd7d7e..82e48954fc 100644 --- a/packages/components/select/src/select.vue +++ b/packages/components/select/src/select.vue @@ -3,7 +3,7 @@ ref="selectRef" v-click-outside:[popperRef]="handleClickOutside" :class="[nsSelect.b(), nsSelect.m(selectSize)]" - @mouseenter="states.inputHovering = true" + @[mouseEnterEventName]="states.inputHovering = true" @mouseleave="states.inputHovering = false" @click.prevent.stop="toggleMenu" > diff --git a/packages/components/select/src/useSelect.ts b/packages/components/select/src/useSelect.ts index ebb1af4969..df4060dbc6 100644 --- a/packages/components/select/src/useSelect.ts +++ b/packages/components/select/src/useSelect.ts @@ -27,6 +27,7 @@ import { debugWarn, isClient, isFunction, + isIOS, isNumber, isUndefined, scrollIntoView, @@ -249,6 +250,12 @@ export const useSelect = (props: ISelectProps, emit) => { : states.selectedLabel }) + // iOS Safari does not handle click events when a mouseenter event is registered and a DOM-change happens in a child + // We use a Vue custom event binding to only register the event on non-iOS devices + // ref.: https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html + // Github Issue: https://github.com/vuejs/vue/issues/9859 + const mouseEnterEventName = computed(() => (isIOS ? null : 'mouseenter')) + watch( () => props.modelValue, (val, oldVal) => { @@ -671,6 +678,10 @@ export const useSelect = (props: ISelectProps, emit) => { const toggleMenu = () => { if (selectDisabled.value) return + // We only set the inputHovering state to true on mouseenter event on iOS devices + // To keep the state updated we set it here to true + if (isIOS) states.inputHovering = true + if (states.menuVisibleOnFocus) { // controlled by automaticDropdown states.menuVisibleOnFocus = false @@ -815,6 +826,7 @@ export const useSelect = (props: ISelectProps, emit) => { hasModelValue, shouldShowPlaceholder, currentPlaceholder, + mouseEnterEventName, showClose, iconComponent, iconReverse,