diff --git a/packages/components/dropdown/__tests__/dropdown.test.ts b/packages/components/dropdown/__tests__/dropdown.test.ts index 28b618845d..d73f62a4ff 100644 --- a/packages/components/dropdown/__tests__/dropdown.test.ts +++ b/packages/components/dropdown/__tests__/dropdown.test.ts @@ -910,4 +910,53 @@ describe('Dropdown', () => { expect(document.body.querySelector(selector.value).innerHTML).toBe('') }) }) + + test('hover trigger: click dropdown-item should close immediately', async () => { + const wrapper = _mount( + ` + + + dropdown + + + + `, + () => ({}) + ) + + await nextTick() + const content = wrapper.findComponent(ElTooltip).vm as InstanceType< + typeof ElTooltip + > + vi.useFakeTimers() + const triggerElm = wrapper.find('.el-tooltip__trigger') + expect(content.open).toBe(false) + await triggerElm.trigger(MOUSE_ENTER_EVENT) + vi.runAllTimers() + await nextTick() + expect(content.open).toBe(true) + + const menu = wrapper.findComponent({ ref: 'menu' }) + await menu.trigger(MOUSE_ENTER_EVENT) + + const item = wrapper + .findComponent({ ref: 'item' }) + .findComponent({ name: 'DropdownItemImpl' }) + .find('.el-dropdown-menu__item') + + await item.trigger('click') + await nextTick() + vi.advanceTimersByTime(100) + expect(content.open).toBe(false) + + await triggerElm.trigger(MOUSE_ENTER_EVENT) + vi.runAllTimers() + await nextTick() + expect(content.open).toBe(true) + vi.useRealTimers() + }) }) diff --git a/packages/components/dropdown/src/dropdown.vue b/packages/components/dropdown/src/dropdown.vue index 7890d1dd58..9bd55ca70c 100644 --- a/packages/components/dropdown/src/dropdown.vue +++ b/packages/components/dropdown/src/dropdown.vue @@ -7,7 +7,6 @@ :fallback-placements="['bottom', 'top']" :popper-options="popperOptions" :gpu-acceleration="false" - :hide-after="trigger === 'hover' ? hideTimeout : 0" :manual-mode="true" :placement="placement" :popper-class="[ns.e('popper'), popperClass]" @@ -17,6 +16,7 @@ :trigger-target-el="contentRef" :show-arrow="showArrow" :show-after="trigger === 'hover' ? showTimeout : 0" + :hide-after="trigger === 'hover' ? hideTimeout : 0" :stop-popper-mouse-event="false" :virtual-ref="virtualRef ?? triggeringElementRef" :virtual-triggering="virtualTriggering || splitButton" @@ -162,7 +162,7 @@ export default defineComponent({ const triggerId = computed(() => props.id || defaultTriggerId) function handleClick() { - handleClose() + popperRef.value?.onClose(undefined, 0) } function handleClose() { diff --git a/packages/hooks/use-delayed-toggle/index.ts b/packages/hooks/use-delayed-toggle/index.ts index 2994e2eb39..f2dc160bf0 100644 --- a/packages/hooks/use-delayed-toggle/index.ts +++ b/packages/hooks/use-delayed-toggle/index.ts @@ -46,7 +46,7 @@ export const useDelayedToggle = ({ cancelTimeout: cancelTimeoutForAutoClose, } = useTimeout() - const onOpen = (event?: Event) => { + const onOpen = (event?: Event, delay = unref(showAfter)) => { registerTimeout(() => { open(event) @@ -56,15 +56,14 @@ export const useDelayedToggle = ({ close(event) }, _autoClose) } - }, unref(showAfter)) + }, delay) } - const onClose = (event?: Event) => { + const onClose = (event?: Event, delay = unref(hideAfter)) => { cancelTimeoutForAutoClose() - registerTimeout(() => { close(event) - }, unref(hideAfter)) + }, delay) } return {