Skip to content

Commit 96ac060

Browse files
authored
refactor: do not call showPopover if only nested overlays are open (#9773)
1 parent 6626b6d commit 96ac060

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

packages/overlay/src/vaadin-overlay-stack-mixin.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ const getAttachedInstances = () =>
2323
*/
2424
const getOverlayInstances = () => getAttachedInstances().filter((el) => el.$.overlay);
2525

26+
/**
27+
* Returns true if all the instances on top of the overlay are nested overlays.
28+
* @private
29+
*/
30+
const hasOnlyNestedOverlays = (overlay) => {
31+
const instances = getAttachedInstances();
32+
const next = instances[instances.indexOf(overlay) + 1];
33+
if (!next) {
34+
return true;
35+
}
36+
37+
if (!overlay._deepContains(next)) {
38+
return false;
39+
}
40+
41+
return hasOnlyNestedOverlays(next);
42+
};
43+
2644
/**
2745
* Returns true if the overlay is the last one in the opened overlays stack.
2846
* @param {HTMLElement} overlay
@@ -99,6 +117,13 @@ export const OverlayStackMixin = (superClass) =>
99117
}
100118
this.style.zIndex = zIndex;
101119

120+
// If the overlay is the last one, or if all other overlays shown above
121+
// are nested overlays (e.g. date-picker inside a dialog), do not call
122+
// `showPopover()` unnecessarily to avoid scroll position being reset.
123+
if (isLastOverlay(this) || hasOnlyNestedOverlays(this)) {
124+
return;
125+
}
126+
102127
// Update stacking order of native popover-based overlays
103128
if (this.matches(':popover-open')) {
104129
this.hidePopover();

packages/overlay/test/multiple.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,41 @@ describe('multiple overlays', () => {
338338
const frontmost = getFrontmostOverlayFromScreenCenter();
339339
expect(frontmost).to.equal(modeless1);
340340
});
341+
342+
it('should not call showPopover on bringToFront if only nested overlay is open', () => {
343+
modeless2.opened = true;
344+
modeless1.showPopover();
345+
modeless2.opened = true;
346+
modeless2.showPopover();
347+
348+
// Mimic nested overlays case
349+
modeless1.appendChild(modeless2);
350+
351+
const showSpy1 = sinon.spy(modeless1, 'showPopover');
352+
const showSpy2 = sinon.spy(modeless2, 'showPopover');
353+
354+
modeless1.bringToFront();
355+
356+
expect(showSpy1).to.be.not.called;
357+
expect(showSpy2).to.be.not.called;
358+
359+
expect(modeless2._last).to.be.true;
360+
});
361+
362+
it('should not call showPopover on bringToFront for the last open overlay', () => {
363+
modeless2.opened = true;
364+
modeless1.showPopover();
365+
modeless2.opened = true;
366+
modeless2.showPopover();
367+
368+
const showSpy2 = sinon.spy(modeless2, 'showPopover');
369+
370+
modeless2.bringToFront();
371+
372+
expect(showSpy2).to.be.not.called;
373+
374+
expect(modeless2._last).to.be.true;
375+
});
341376
});
342377
});
343378

@@ -362,6 +397,13 @@ describe('multiple overlays', () => {
362397
root.appendChild(btn);
363398
}
364399
};
400+
el.opened = true;
401+
});
402+
});
403+
404+
afterEach(() => {
405+
overlays.forEach((el) => {
406+
el.opened = false;
365407
});
366408
});
367409

0 commit comments

Comments
 (0)