diff --git a/packages/overlay/src/vaadin-overlay-position-mixin.js b/packages/overlay/src/vaadin-overlay-position-mixin.js index 988d0cf79d..9bec60ecfe 100644 --- a/packages/overlay/src/vaadin-overlay-position-mixin.js +++ b/packages/overlay/src/vaadin-overlay-position-mixin.js @@ -146,9 +146,12 @@ export const PositionMixin = (superClass) => /** @private */ __addUpdatePositionEventListeners() { - window.addEventListener('resize', this._updatePosition); + window.visualViewport.addEventListener('resize', this._updatePosition); + window.visualViewport.addEventListener('scroll', this.__onScroll, true); - this.__positionTargetAncestorRootNodes = getAncestorRootNodes(this.positionTarget); + this.__positionTargetAncestorRootNodes = getAncestorRootNodes(this.positionTarget).filter( + (node) => node !== document, + ); this.__positionTargetAncestorRootNodes.forEach((node) => { node.addEventListener('scroll', this.__onScroll, true); }); @@ -156,7 +159,8 @@ export const PositionMixin = (superClass) => /** @private */ __removeUpdatePositionEventListeners() { - window.removeEventListener('resize', this._updatePosition); + window.visualViewport.removeEventListener('resize', this._updatePosition); + window.visualViewport.removeEventListener('scroll', this.__onScroll, true); if (this.__positionTargetAncestorRootNodes) { this.__positionTargetAncestorRootNodes.forEach((node) => { @@ -204,9 +208,11 @@ export const PositionMixin = (superClass) => /** @private */ __onScroll(e) { // If the scroll event occurred inside the overlay, ignore it. - if (!this.contains(e.target)) { - this._updatePosition(); + if (e.target instanceof Node && this.contains(e.target)) { + return; } + + this._updatePosition(); } _updatePosition() { diff --git a/packages/overlay/test/position-mixin-listeners.test.js b/packages/overlay/test/position-mixin-listeners.test.js index 0eb0587094..5c6431feb2 100644 --- a/packages/overlay/test/position-mixin-listeners.test.js +++ b/packages/overlay/test/position-mixin-listeners.test.js @@ -68,8 +68,8 @@ describe('position mixin listeners', () => { updatePositionSpy.resetHistory(); }); - it('should not update position on resize', () => { - resize(window); + it('should not update position on visual viewport resize', () => { + resize(window.visualViewport); expect(updatePositionSpy.called).to.be.false; }); @@ -84,17 +84,17 @@ describe('position mixin listeners', () => { expect(updatePositionSpy.called).to.be.false; }); - it('should update position on resize after assigning a position target', () => { + it('should update position on visual viewport resize after assigning a position target', () => { overlay.positionTarget = target; updatePositionSpy.resetHistory(); - resize(window); + resize(window.visualViewport); expect(updatePositionSpy.called).to.be.true; }); - it('should update position on document scroll after assigning a position target', () => { + it('should update position on visual viewport scroll after assigning a position target', () => { overlay.positionTarget = target; updatePositionSpy.resetHistory(); - scroll(document); + scroll(window.visualViewport); expect(updatePositionSpy.called).to.be.true; }); @@ -126,14 +126,35 @@ describe('position mixin listeners', () => { updatePositionSpy.resetHistory(); }); - it('should update position on resize', () => { + it('should not update position on window resize', () => { resize(window); + expect(updatePositionSpy.called).to.be.false; + }); + + it('should not update position on document scroll', () => { + scroll(document); + expect(updatePositionSpy.called).to.be.false; + }); + + it('should update position on visual viewport resize', () => { + resize(window.visualViewport); expect(updatePositionSpy.called).to.be.true; }); - it('should not update position on resize when closed', () => { + it('should not update position on visual viewport resize when closed', () => { overlay.opened = false; - resize(window); + resize(window.visualViewport); + expect(updatePositionSpy.called).to.be.false; + }); + + it('should update position on visual viewport scroll', () => { + scroll(window.visualViewport); + expect(updatePositionSpy.called).to.be.true; + }); + + it('should not update position on visual viewport scroll when closed', () => { + overlay.opened = false; + scroll(window.visualViewport); expect(updatePositionSpy.called).to.be.false; }); @@ -150,13 +171,13 @@ describe('position mixin listeners', () => { expect(updatePositionSpy.called).to.be.false; }); - ['document', 'ancestor'].forEach((name) => { + ['visual viewport', 'ancestor'].forEach((name) => { describe(name, () => { let scrollableNode; beforeEach(() => { - if (name === 'document') { - scrollableNode = document; + if (name === 'visual viewport') { + scrollableNode = window.visualViewport; } if (name === 'ancestor') { scrollableNode = wrapper.shadowRoot.querySelector('#scrollable'); @@ -208,8 +229,8 @@ describe('position mixin listeners', () => { updatePositionSpy.resetHistory(); }); - it('should update position on document scroll', () => { - scroll(document); + it('should update position on visual viewport scroll', () => { + scroll(window.visualViewport); expect(updatePositionSpy.called).to.be.true; }); @@ -234,8 +255,8 @@ describe('position mixin listeners', () => { newWrapper.appendChild(target); }); - it('should update position on document scroll after re-opened', async () => { - scroll(document); + it('should update position on visual viewport scroll after re-opened', async () => { + scroll(window.visualViewport); expect(updatePositionSpy.called).to.be.true; overlay.opened = false; @@ -243,7 +264,7 @@ describe('position mixin listeners', () => { await nextFrame(); updatePositionSpy.resetHistory(); - scroll(document); + scroll(window.visualViewport); expect(updatePositionSpy.called).to.be.true; });