From ff76c4a8b666073e358167d0ec45b565df30c8a8 Mon Sep 17 00:00:00 2001 From: Tyson Cleary Date: Mon, 29 Jan 2018 21:31:04 -0800 Subject: [PATCH] [Overlay] Support nested overlays (#2033) --- .../core/src/components/overlay/overlay.tsx | 15 +++++++++++---- packages/core/test/overlay/overlayTests.tsx | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/core/src/components/overlay/overlay.tsx b/packages/core/src/components/overlay/overlay.tsx index c84f00317a..993d326259 100644 --- a/packages/core/src/components/overlay/overlay.tsx +++ b/packages/core/src/components/overlay/overlay.tsx @@ -138,7 +138,7 @@ export class Overlay extends React.PureComponent { private static getLastOpened = () => Overlay.openStack[Overlay.openStack.length - 1]; // an HTMLElement that contains the backdrop and any children, to query for focus target - private containerElement: HTMLElement; + public containerElement: HTMLElement; private refHandlers = { container: (ref: HTMLDivElement) => (this.containerElement = ref), }; @@ -349,10 +349,17 @@ export class Overlay extends React.PureComponent { }; private handleDocumentClick = (e: MouseEvent) => { - const { isOpen, onClose } = this.props; + const { canOutsideClickClose, isOpen, onClose } = this.props; const eventTarget = e.target as HTMLElement; - const isClickInOverlay = this.containerElement != null && this.containerElement.contains(eventTarget); - if (isOpen && this.props.canOutsideClickClose && !isClickInOverlay) { + + const { openStack } = Overlay; + const stackIndex = openStack.indexOf(this); + + const isClickInThisOverlayOrDescendant = openStack + .slice(stackIndex) + .some(({ containerElement }) => containerElement && containerElement.contains(eventTarget)); + + if (isOpen && canOutsideClickClose && !isClickInThisOverlayOrDescendant) { // casting to any because this is a native event safeInvoke(onClose, e as any); } diff --git a/packages/core/test/overlay/overlayTests.tsx b/packages/core/test/overlay/overlayTests.tsx index 374becdf37..3849fe80ed 100644 --- a/packages/core/test/overlay/overlayTests.tsx +++ b/packages/core/test/overlay/overlayTests.tsx @@ -139,6 +139,23 @@ describe("", () => { assert.isTrue(onClose.notCalled); }); + it("not invoked on click of a nested overlay", () => { + const onClose = spy(); + mount( + +
+ {createOverlayContents()} + +
{createOverlayContents()}
+
+
+
, + ) + .find("#inner-element") + .simulate("mousedown"); + assert.isTrue(onClose.notCalled); + }); + it("invoked on escape key", () => { const onClose = spy(); mount(