Skip to content

Commit 3681622

Browse files
authored
refactor: reset overlay position when positionTarget is removed (#10107)
1 parent 71d38cb commit 3681622

File tree

2 files changed

+87
-11
lines changed

2 files changed

+87
-11
lines changed

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

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,6 @@ export const PositionMixin = (superClass) =>
116116
};
117117
}
118118

119-
static get observers() {
120-
return [
121-
'__positionSettingsChanged(horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap, requiredVerticalSpace)',
122-
'__overlayOpenedChanged(opened, positionTarget)',
123-
];
124-
}
125-
126119
constructor() {
127120
super();
128121

@@ -145,6 +138,30 @@ export const PositionMixin = (superClass) =>
145138
this.__removeUpdatePositionEventListeners();
146139
}
147140

141+
/** @protected */
142+
updated(props) {
143+
super.updated(props);
144+
145+
if (props.has('opened') || props.has('positionTarget')) {
146+
if (!this.positionTarget && props.get('positionTarget')) {
147+
this.__resetPosition();
148+
}
149+
150+
this.__overlayOpenedChanged(this.opened, this.positionTarget);
151+
}
152+
153+
const positionProps = [
154+
'horizontalAlign',
155+
'verticalAlign',
156+
'noHorizontalOverlap',
157+
'noVerticalOverlap',
158+
'requiredVerticalSpace',
159+
];
160+
if (positionProps.some((prop) => props.has(prop))) {
161+
this._updatePosition();
162+
}
163+
}
164+
148165
/** @private */
149166
__addUpdatePositionEventListeners() {
150167
window.visualViewport.addEventListener('resize', this._updatePosition);
@@ -210,10 +227,6 @@ export const PositionMixin = (superClass) =>
210227
}
211228
}
212229

213-
__positionSettingsChanged() {
214-
this._updatePosition();
215-
}
216-
217230
/** @private */
218231
__onScroll(e) {
219232
// If the scroll event occurred inside the overlay, ignore it.
@@ -224,6 +237,23 @@ export const PositionMixin = (superClass) =>
224237
this._updatePosition();
225238
}
226239

240+
/** @private */
241+
__resetPosition() {
242+
Object.assign(this.style, {
243+
justifyContent: '',
244+
alignItems: '',
245+
top: '',
246+
bottom: '',
247+
left: '',
248+
right: '',
249+
});
250+
251+
setOverlayStateAttribute(this, 'bottom-aligned', false);
252+
setOverlayStateAttribute(this, 'top-aligned', false);
253+
setOverlayStateAttribute(this, 'end-aligned', false);
254+
setOverlayStateAttribute(this, 'start-aligned', false);
255+
}
256+
227257
_updatePosition() {
228258
if (!this.positionTarget || !this.opened || !this.__margins) {
229259
return;

packages/overlay/test/position-mixin.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ describe('position mixin', () => {
106106
expect(overlay.opened).to.be.false;
107107
});
108108

109+
it('should reset styles when positionTarget is reset', async () => {
110+
overlay.positionTarget = null;
111+
await nextRender();
112+
113+
expect(overlay.style.top).to.equal('');
114+
expect(overlay.style.bottom).to.equal('');
115+
expect(overlay.style.left).to.equal('');
116+
expect(overlay.style.right).to.equal('');
117+
expect(overlay.style.alignItems).to.equal('');
118+
expect(overlay.style.justifyContent).to.equal('');
119+
});
120+
109121
describe('vertical align top', () => {
110122
beforeEach(() => {
111123
overlay.verticalAlign = TOP;
@@ -125,6 +137,13 @@ describe('position mixin', () => {
125137
expect(parent.hasAttribute('bottom-aligned')).to.be.false;
126138
});
127139

140+
it('should remove top-aligned attribute when positionTarget is reset', async () => {
141+
overlay.positionTarget = null;
142+
await nextRender();
143+
expect(overlay.hasAttribute('top-aligned')).to.be.false;
144+
expect(parent.hasAttribute('top-aligned')).to.be.false;
145+
});
146+
128147
it('should align top edges when overlay part is animated', async () => {
129148
overlay.classList.add('animated');
130149
await oneEvent(overlay.$.overlay, 'animationend');
@@ -146,6 +165,16 @@ describe('position mixin', () => {
146165
expect(parent.hasAttribute('bottom-aligned')).to.be.true;
147166
});
148167

168+
it('should bottom top-aligned attribute when positionTarget is reset', async () => {
169+
target.style.top = `${targetPositionToFlipOverlay + 3}px`;
170+
updatePosition();
171+
172+
overlay.positionTarget = null;
173+
await nextRender();
174+
expect(overlay.hasAttribute('bottom-aligned')).to.be.false;
175+
expect(parent.hasAttribute('bottom-aligned')).to.be.false;
176+
});
177+
149178
it('should flip when out of space and squeezed smaller than current available space', () => {
150179
target.style.top = `${targetPositionToFlipOverlay + 3}px`;
151180

@@ -384,6 +413,13 @@ describe('position mixin', () => {
384413
expect(parent.hasAttribute('end-aligned')).to.be.false;
385414
});
386415

416+
it('should remove start-aligned attribute when positionTarget is reset', async () => {
417+
overlay.positionTarget = null;
418+
await nextRender();
419+
expect(overlay.hasAttribute('start-aligned')).to.be.false;
420+
expect(parent.hasAttribute('start-aligned')).to.be.false;
421+
});
422+
387423
it('should align right edges with right-to-left', async () => {
388424
document.dir = 'rtl';
389425
await nextRender();
@@ -407,6 +443,16 @@ describe('position mixin', () => {
407443
expect(parent.hasAttribute('end-aligned')).to.be.true;
408444
});
409445

446+
it('should remove end-aligned attribute when positionTarget is reset', async () => {
447+
target.style.left = `${targetPositionToFlipOverlay + 3}px`;
448+
updatePosition();
449+
450+
overlay.positionTarget = null;
451+
await nextRender();
452+
expect(overlay.hasAttribute('end-aligned')).to.be.false;
453+
expect(parent.hasAttribute('end-aligned')).to.be.false;
454+
});
455+
410456
it('should flip when out of space and squeezed smaller than current available space', () => {
411457
target.style.left = `${targetPositionToFlipOverlay + 3}px`;
412458

0 commit comments

Comments
 (0)