diff --git a/packages/overlays/src/OverlayMixin.js b/packages/overlays/src/OverlayMixin.js index 41ec83803..a1e2cc0ad 100644 --- a/packages/overlays/src/OverlayMixin.js +++ b/packages/overlays/src/OverlayMixin.js @@ -86,10 +86,12 @@ export const OverlayMixin = dedupeMixin( updated(changedProperties) { super.updated(changedProperties); - if (changedProperties.has('opened')) { - if (this._overlayCtrl) { - this.__syncToOverlayController(); - } + if ( + changedProperties.has('opened') && + this._overlayCtrl && + !this.__blockSyncToOverlayCtrl + ) { + this.__syncToOverlayController(); } } @@ -210,6 +212,13 @@ export const OverlayMixin = dedupeMixin( this._overlayCtrl.teardown(); } + async _setOpenedWithoutPropertyEffects(newOpened) { + this.__blockSyncToOverlayCtrl = true; + this.opened = newOpened; + await this.updateComplete; + this.__blockSyncToOverlayCtrl = false; + } + __setupSyncFromOverlayController() { this.__onOverlayCtrlShow = () => { this.opened = true; @@ -223,6 +232,8 @@ export const OverlayMixin = dedupeMixin( const event = new CustomEvent('before-opened', { cancelable: true }); this.dispatchEvent(event); if (event.defaultPrevented) { + // Check whether our current `.opened` state is not out of sync with overlayCtrl + this._setOpenedWithoutPropertyEffects(this._overlayCtrl.isShown); beforeShowEvent.preventDefault(); } }; @@ -231,6 +242,8 @@ export const OverlayMixin = dedupeMixin( const event = new CustomEvent('before-closed', { cancelable: true }); this.dispatchEvent(event); if (event.defaultPrevented) { + // Check whether our current `.opened` state is not out of sync with overlayCtrl + this._setOpenedWithoutPropertyEffects(this._overlayCtrl.isShown); beforeHideEvent.preventDefault(); } }; diff --git a/packages/overlays/stories/demo-overlay-system.js b/packages/overlays/stories/demo-overlay-system.js index 14c52cb49..704b014a6 100644 --- a/packages/overlays/stories/demo-overlay-system.js +++ b/packages/overlays/stories/demo-overlay-system.js @@ -32,6 +32,7 @@ class DemoOverlaySystem extends OverlayMixin(LitElement) { +
popup is ${this.opened ? 'opened' : 'closed'}
`; } } diff --git a/packages/overlays/test-suites/OverlayMixin.suite.js b/packages/overlays/test-suites/OverlayMixin.suite.js index c74176d67..70e5815a1 100644 --- a/packages/overlays/test-suites/OverlayMixin.suite.js +++ b/packages/overlays/test-suites/OverlayMixin.suite.js @@ -113,7 +113,14 @@ export function runOverlayMixinSuite({ /* tagString, */ tag, suffix = '' }) { `); - await el._overlayCtrl.show(); + el.querySelector('[slot="invoker"]').click(); + await nextFrame(); + expect(el.opened).to.be.false; + + // Also, the opened state should be synced back to that of the OverlayController + el.opened = true; + expect(el.opened).to.be.true; + await nextFrame(); expect(el.opened).to.be.false; });