diff --git a/docs/examples/body-overflow.tsx b/docs/examples/body-overflow.tsx
index 58997c7f..b6ab5182 100644
--- a/docs/examples/body-overflow.tsx
+++ b/docs/examples/body-overflow.tsx
@@ -1,8 +1,26 @@
/* eslint no-console:0 */
import Trigger from 'rc-trigger';
import React from 'react';
+import { createPortal } from 'react-dom';
import '../../assets/index.less';
+const PortalDemo = () => {
+ return createPortal(
+
+ PortalNode
+
,
+ document.body,
+ );
+};
+
export default () => {
const [open, setOpen] = React.useState(false);
const [open1, setOpen1] = React.useState(false);
@@ -47,6 +65,8 @@ export default () => {
>
Close
+
+
}
// popupVisible
diff --git a/src/index.tsx b/src/index.tsx
index 074ad58b..4ee07ed4 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -337,11 +337,14 @@ export function generateTrigger(
// ========================== Motion ============================
const [inMotion, setInMotion] = React.useState(false);
- useLayoutEffect((firstMount) => {
- if (!firstMount || mergedOpen) {
- setInMotion(true);
- }
- }, [mergedOpen]);
+ useLayoutEffect(
+ (firstMount) => {
+ if (!firstMount || mergedOpen) {
+ setInMotion(true);
+ }
+ },
+ [mergedOpen],
+ );
const [motionPrepareResolve, setMotionPrepareResolve] =
React.useState(null);
@@ -522,7 +525,10 @@ export function generateTrigger(
setMousePosByEvent(event);
});
onPopupMouseEnter = () => {
- triggerOpen(true, mouseEnterDelay);
+ // Only trigger re-open when popup is visible
+ if (mergedOpen || inMotion) {
+ triggerOpen(true, mouseEnterDelay);
+ }
};
// Align Point
@@ -613,9 +619,9 @@ export function generateTrigger(
const innerArrow: ArrowTypeOuter = arrow
? {
- // true and Object likely
- ...(arrow !== true ? arrow : {}),
- }
+ // true and Object likely
+ ...(arrow !== true ? arrow : {}),
+ }
: null;
// Render
diff --git a/tests/basic.test.jsx b/tests/basic.test.jsx
index 254cb58b..19b59850 100644
--- a/tests/basic.test.jsx
+++ b/tests/basic.test.jsx
@@ -36,14 +36,14 @@ describe('Trigger.Basic', () => {
.className.includes('-hidden');
}
function isPopupClassHidden(name) {
- return document
- .querySelector(name).className.includes('-hidden')
+ return document.querySelector(name).className.includes('-hidden');
}
function isPopupAllHidden() {
- const popupArr = document
- .querySelectorAll('.rc-trigger-popup')
-
- return Array.from(popupArr).every(item => item.className.includes('-hidden'))
+ const popupArr = document.querySelectorAll('.rc-trigger-popup');
+
+ return Array.from(popupArr).every((item) =>
+ item.className.includes('-hidden'),
+ );
}
describe('getPopupContainer', () => {
it('defaults to document.body', () => {
@@ -176,7 +176,7 @@ describe('Trigger.Basic', () => {
<>
trigger1}
@@ -186,7 +186,7 @@ describe('Trigger.Basic', () => {
trigger2}
>
@@ -194,7 +194,7 @@ describe('Trigger.Basic', () => {
>,
);
-
+
trigger(container, '.target1', 'contextMenu');
trigger(container, '.target2', 'contextMenu');
expect(isPopupClassHidden('.trigger-popup1')).toBeTruthy();
@@ -882,7 +882,7 @@ describe('Trigger.Basic', () => {
});
it('find real dom node if children not support `forwardRef`', () => {
- const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
+ const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const Node = () => ;
render(
@@ -1066,4 +1066,30 @@ describe('Trigger.Basic', () => {
expect(document.querySelector('.rc-trigger-popup-hidden')).toBeFalsy();
});
});
+
+ it('not trigger open when hover hidden popup node', () => {
+ const onPopupVisibleChange = jest.fn();
+
+ const { container } = render(
+ trigger}
+ getPopupContainer={() => container}
+ >
+
+ ,
+ );
+
+ trigger(container, '.target', 'mouseEnter');
+ expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
+ onPopupVisibleChange.mockReset();
+
+ trigger(container, '.target', 'mouseLeave');
+ expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
+ onPopupVisibleChange.mockReset();
+
+ trigger(container, '.popup', 'mouseEnter');
+ expect(onPopupVisibleChange).not.toHaveBeenCalled();
+ });
});