diff --git a/packages/overlays/src/OverlayController.js b/packages/overlays/src/OverlayController.js index 22fd296fd..f92b871da 100644 --- a/packages/overlays/src/OverlayController.js +++ b/packages/overlays/src/OverlayController.js @@ -32,6 +32,7 @@ export class OverlayController { preventsScroll: false, trapsKeyboardFocus: false, hidesOnEsc: false, + hidesOnOutsideEsc: false, hidesOnOutsideClick: false, isTooltip: false, handlesUserInteraction: false, @@ -376,6 +377,9 @@ export class OverlayController { if (this.hidesOnEsc) { this._handleHidesOnEsc({ phase }); } + if (this.hidesOnOutsideEsc) { + this._handleHidesOnOutsideEsc({ phase }); + } if (this.hidesOnOutsideClick) { this._handleHidesOnOutsideClick({ phase }); } @@ -537,6 +541,15 @@ export class OverlayController { } } + _handleHidesOnOutsideEsc({ phase }) { + if (phase === 'show') { + this.__escKeyHandler = ev => ev.key === 'Escape' && this.hide(); + document.addEventListener('keyup', this.__escKeyHandler); + } else if (phase === 'hide') { + document.removeEventListener('keyup', this.__escKeyHandler); + } + } + _handleInheritsReferenceWidth() { if (!this._referenceNode) { return; diff --git a/packages/overlays/test/OverlayController.test.js b/packages/overlays/test/OverlayController.test.js index e31b59a57..f8d607f48 100644 --- a/packages/overlays/test/OverlayController.test.js +++ b/packages/overlays/test/OverlayController.test.js @@ -314,6 +314,29 @@ describe('OverlayController', () => { }); }); + describe('hidesOnOutsideEsc', () => { + it('hides when [escape] is pressed on outside element', async () => { + const ctrl = new OverlayController({ + ...withGlobalTestConfig(), + hidesOnOutsideEsc: true, + }); + await ctrl.show(); + document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' })); + await aTimeout(); + expect(ctrl.isShown).to.be.false; + }); + + it('stays shown when [escape] is pressed on inside element', async () => { + const ctrl = new OverlayController({ + ...withGlobalTestConfig(), + hidesOnOutsideEsc: true, + }); + await ctrl.show(); + ctrl.contentNode.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' })); + expect(ctrl.isShown).to.be.true; + }); + }); + describe('hidesOnOutsideClick', () => { it('hides on outside click', async () => { const contentNode = await fixture('