diff --git a/packages/fluentui/e2e/cypress/support/commands.js b/packages/fluentui/e2e/cypress/support/commands.js index 7c6ec4b8dbf7c1..d1b09afccffb16 100644 --- a/packages/fluentui/e2e/cypress/support/commands.js +++ b/packages/fluentui/e2e/cypress/support/commands.js @@ -36,6 +36,10 @@ Cypress.Commands.add('clickOn', selector => { cy.get(selector).realClick(); }); +Cypress.Commands.add('mouseDownOn', selector => { + cy.get(selector).trigger('mousedown'); +}); + Cypress.Commands.add('focusOn', selector => { cy.get(selector).focus(); }); diff --git a/packages/fluentui/e2e/cypress/support/index.d.ts b/packages/fluentui/e2e/cypress/support/index.d.ts index b6c3851b6e5d70..fff47ab8c0e96b 100644 --- a/packages/fluentui/e2e/cypress/support/index.d.ts +++ b/packages/fluentui/e2e/cypress/support/index.d.ts @@ -31,6 +31,7 @@ declare namespace Cypress { nothingIsFocused(): Chainable; simulatePageMove(): Chainable; clickOn(selector: string): Chainable; + mouseDownOn(selector: string): Chainable; focusOn(selector: string): Chainable; hover(selector: string): Chainable; resizeViewport(width: number): Chainable; diff --git a/packages/fluentui/e2e/tests/popupMouseDownSelecting-example.tsx b/packages/fluentui/e2e/tests/popupMouseDownSelecting-example.tsx new file mode 100644 index 00000000000000..25ad66bdc6e8e0 --- /dev/null +++ b/packages/fluentui/e2e/tests/popupMouseDownSelecting-example.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { Popup, Button, buttonClassName, popupContentClassName } from '@fluentui/react-northstar'; + +export const selectors = { + popupContent: popupContentClassName, + button: buttonClassName, + secondDiv: 'second-div', +}; + +const PopupWithoutTriggerExample = () => { + return ( +
+ } + /> +
+
+ ); +}; + +export default PopupWithoutTriggerExample; diff --git a/packages/fluentui/e2e/tests/popupMouseDownSelecting.spec.ts b/packages/fluentui/e2e/tests/popupMouseDownSelecting.spec.ts new file mode 100644 index 00000000000000..b2e80ea7d6505d --- /dev/null +++ b/packages/fluentui/e2e/tests/popupMouseDownSelecting.spec.ts @@ -0,0 +1,15 @@ +describe('Popup without `trigger`', () => { + const selectors = { popupContent: 'ui-popup__content', button: 'ui-button' }; + const button = `.${selectors.button}`; + const popupContent = `.${selectors.popupContent}`; + + beforeEach(() => { + cy.gotoTestCase(__filename, button); + }); + + it('Popup still open on mousedown event', () => { + cy.clickOn(button); + cy.get(popupContent).trigger('mousedown', { which: 1 }).trigger('mousemove', { clientX: 300, clientY: 300 }); + cy.visible(popupContent); + }); +}); diff --git a/packages/fluentui/react-northstar/src/components/Popup/Popup.tsx b/packages/fluentui/react-northstar/src/components/Popup/Popup.tsx index edcfdc78bda177..92df91c9a7e215 100644 --- a/packages/fluentui/react-northstar/src/components/Popup/Popup.tsx +++ b/packages/fluentui/react-northstar/src/components/Popup/Popup.tsx @@ -175,7 +175,7 @@ export const Popup: React.FC & const [isOpenedByRightClick, setIsOpenedByRightClick] = React.useState(false); const closeTimeoutId = React.useRef(); - + const mouseDownEventRef = React.useRef(); const popupContentRef = React.useRef(); const pointerTargetRef = React.useRef(); const triggerRef = React.useRef(); @@ -230,6 +230,13 @@ export const Popup: React.FC & }); const handleDocumentClick = (getRefs: Function) => (e: MouseEvent) => { + const currentMouseDownEvent = mouseDownEventRef.current; + mouseDownEventRef.current = null; + + if (currentMouseDownEvent && !isOutsidePopupElement(getRefs(), currentMouseDownEvent)) { + return; + } + if (isOpenedByRightClick && isOutsidePopupElement(getRefs(), e)) { trySetOpen(false, e); rightClickReferenceObject.current = null; @@ -241,6 +248,10 @@ export const Popup: React.FC & } }; + const handleMouseDown = (e: MouseEvent) => { + mouseDownEventRef.current = e; + }; + const handleDocumentKeyDown = (getRefs: Function) => (e: KeyboardEvent) => { const keyCode = getCode(e); const isMatchingKey = keyCode === keyboardKey.Enter || keyCode === SpacebarKey; @@ -439,6 +450,7 @@ export const Popup: React.FC & {context.target && ( <> +