Skip to content

Commit b9f1674

Browse files
authored
refactor!: use slotted div element as a dialog renderer root (#10367)
1 parent d01119c commit b9f1674

File tree

13 files changed

+100
-51
lines changed

13 files changed

+100
-51
lines changed

packages/context-menu/src/vaadin-menu-overlay-mixin.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,20 @@ export const MenuOverlayMixin = (superClass) =>
3737
}
3838

3939
/**
40-
* Override method from OverlayFocusMixin to use slotted div as the content root.
40+
* Override method from OverlayFocusMixin to use slotted div as content root.
4141
* @protected
4242
* @override
4343
*/
4444
get _contentRoot() {
45+
return this._rendererRoot;
46+
}
47+
48+
/**
49+
* Override method from OverlayMixin to use slotted div as the renderer root.
50+
* @protected
51+
* @override
52+
*/
53+
get _rendererRoot() {
4554
if (!this.__savedRoot) {
4655
const root = document.createElement('div');
4756
root.setAttribute('slot', 'overlay');

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

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ export const DialogOverlayMixin = (superClass) =>
5353
return this.owner;
5454
}
5555

56+
/**
57+
* Override method from OverlayMixin to use slotted div as a renderer root.
58+
* @protected
59+
* @override
60+
*/
61+
get _rendererRoot() {
62+
if (!this.__savedRoot) {
63+
const root = document.createElement('div');
64+
root.style.display = 'contents';
65+
this.owner.appendChild(root);
66+
this.__savedRoot = root;
67+
}
68+
69+
return this.__savedRoot;
70+
}
71+
5672
/** @protected */
5773
ready() {
5874
super.ready();
@@ -98,8 +114,9 @@ export const DialogOverlayMixin = (superClass) =>
98114
// Reset existing container in case if a new renderer is set.
99115
this.__clearContainer(container);
100116
} else {
101-
// Create the container, but wait to append it until requestContentUpdate is called.
117+
// Create the container and append it to the dialog element.
102118
container = this.__createContainer(slot);
119+
this.owner.appendChild(container);
103120
}
104121
return container;
105122
}
@@ -181,28 +198,12 @@ export const DialogOverlayMixin = (superClass) =>
181198
requestContentUpdate() {
182199
super.requestContentUpdate();
183200

184-
if (this.headerContainer) {
185-
// If a new renderer has been set, make sure to reattach the container
186-
if (!this.headerContainer.parentElement) {
187-
this.owner.appendChild(this.headerContainer);
188-
}
189-
190-
if (this.headerRenderer) {
191-
// Only call header renderer after the container has been initialized
192-
this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
193-
}
201+
if (this.headerContainer && this.headerRenderer) {
202+
this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
194203
}
195204

196-
if (this.footerContainer) {
197-
// If a new renderer has been set, make sure to reattach the container
198-
if (!this.footerContainer.parentElement) {
199-
this.owner.appendChild(this.footerContainer);
200-
}
201-
202-
if (this.footerRenderer) {
203-
// Only call header renderer after the container has been initialized
204-
this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
205-
}
205+
if (this.footerContainer && this.footerRenderer) {
206+
this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
206207
}
207208

208209
this._headerTitleRenderer();

packages/dialog/test/dom/__snapshots__/dialog.test.snap.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ snapshots["vaadin-dialog host"] =
99
tabindex="0"
1010
with-backdrop=""
1111
>
12-
content
12+
<div>
13+
content
14+
</div>
1315
</vaadin-dialog>
1416
`;
1517
/* end snapshot vaadin-dialog host */

packages/dialog/test/draggable-resizable.test.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,20 +235,21 @@ describe('resizable', () => {
235235
});
236236

237237
it('should support scrollable full size content', () => {
238-
const container = dialog.firstElementChild;
239-
container.style.height = '100%';
240-
container.style.width = '100%';
241-
container.style.overflow = 'auto';
242-
container.textContent = new Array(10000).fill('foo').join(' ');
238+
const contentElement = dialog.$.overlay._rendererRoot.firstElementChild;
239+
contentElement.style.height = '100%';
240+
contentElement.style.width = '100%';
241+
contentElement.style.overflow = 'auto';
242+
contentElement.textContent = new Array(10000).fill('foo').join(' ');
243243

244244
const resizeContainer = dialog.$.overlay.$.resizerContainer;
245-
expect(container.offsetHeight).to.equal(resizeContainer.offsetHeight);
245+
expect(contentElement.offsetHeight).to.equal(resizeContainer.offsetHeight);
246246
});
247247

248248
it('should scroll if the content overflows', async () => {
249249
// Fill the content with a lot of text so that it overflows the viewport
250-
dialog.firstElementChild.textContent = new Array(10000).fill('foo').join(' ');
251-
await nextResize(dialog.firstElementChild);
250+
const contentElement = dialog.$.overlay._rendererRoot.firstElementChild;
251+
contentElement.textContent = new Array(10000).fill('foo').join(' ');
252+
await nextResize(contentElement);
252253
await nextRender();
253254

254255
const content = dialog.$.overlay.$.content;
@@ -260,9 +261,10 @@ describe('resizable', () => {
260261
resize(overlayPart.querySelector('.s'), 0, 10);
261262

262263
// Set the dialog content to have 100% height
263-
dialog.firstElementChild.style.height = '100%';
264+
const contentElement = dialog.$.overlay._rendererRoot.firstElementChild;
265+
contentElement.style.height = '100%';
264266

265-
const contentBounds = dialog.firstElementChild.getBoundingClientRect();
267+
const contentBounds = contentElement.getBoundingClientRect();
266268
const overlayBounds = overlayPart.getBoundingClientRect();
267269
expect(Math.floor(contentBounds.height)).to.equal(Math.floor(overlayBounds.height));
268270
});
@@ -579,7 +581,7 @@ describe('draggable', () => {
579581
dialog.height = '100px';
580582
await nextRender();
581583

582-
const contentElement = dialog.firstElementChild;
584+
const contentElement = dialog.$.overlay._rendererRoot.firstElementChild;
583585
contentElement.style.minHeight = '200px';
584586
await nextResize(contentElement);
585587
await nextRender();

packages/dialog/test/renderer.test.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sinon from 'sinon';
44
import '../src/vaadin-dialog.js';
55

66
describe('vaadin-dialog renderer', () => {
7-
let dialog;
7+
let dialog, rendererRoot;
88

99
beforeEach(async () => {
1010
dialog = fixtureSync('<vaadin-dialog></vaadin-dialog>');
@@ -20,7 +20,8 @@ describe('vaadin-dialog renderer', () => {
2020
dialog.opened = true;
2121
await nextRender();
2222

23-
expect(dialog.textContent).to.include('The content of the dialog');
23+
rendererRoot = dialog.firstElementChild;
24+
expect(rendererRoot.textContent).to.include('The content of the dialog');
2425
});
2526

2627
it('should run renderers when requesting content update', async () => {
@@ -48,11 +49,13 @@ describe('vaadin-dialog renderer', () => {
4849
dialog.opened = true;
4950
await nextRender();
5051

51-
expect(dialog.textContent).to.equal('foo');
52+
rendererRoot = dialog.firstElementChild;
53+
54+
expect(rendererRoot.textContent).to.equal('foo');
5255

5356
dialog.renderer = null;
5457
await nextUpdate(dialog);
5558

56-
expect(dialog.textContent).to.equal('');
59+
expect(rendererRoot.textContent).to.equal('');
5760
});
5861
});

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ export const OverlayMixin = (superClass) =>
102102
return ['_rendererOrDataChanged(renderer, owner, model, opened)'];
103103
}
104104

105+
/**
106+
* Override to specify another element used as a renderer root,
107+
* e.g. slotted into the overlay, rather than overlay itself.
108+
* @protected
109+
*/
110+
get _rendererRoot() {
111+
return this;
112+
}
113+
105114
constructor() {
106115
super();
107116

@@ -175,7 +184,7 @@ export const OverlayMixin = (superClass) =>
175184
*/
176185
requestContentUpdate() {
177186
if (this.renderer) {
178-
this.renderer.call(this.owner, this._contentRoot, this.owner, this.model);
187+
this.renderer.call(this.owner, this._rendererRoot, this.owner, this.model);
179188
}
180189
}
181190

@@ -295,11 +304,11 @@ export const OverlayMixin = (superClass) =>
295304
this._oldOpened = opened;
296305

297306
if (rendererChanged && hasOldRenderer) {
298-
this._contentRoot.innerHTML = '';
307+
this._rendererRoot.innerHTML = '';
299308
// Whenever a Lit-based renderer is used, it assigns a Lit part to the node it was rendered into.
300309
// When clearing the rendered content, this part needs to be manually disposed of.
301310
// Otherwise, using a Lit-based renderer on the same node will throw an exception or render nothing afterward.
302-
delete this._contentRoot._$litPart$;
311+
delete this._rendererRoot._$litPart$;
303312
}
304313

305314
if (opened && renderer && (rendererChanged || openedChanged || ownerOrModelChanged)) {

packages/overlay/test/renderer.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ describe('renderer', () => {
158158
customElements.define(
159159
'custom-root-overlay',
160160
class extends Overlay {
161-
get _contentRoot() {
161+
get _rendererRoot() {
162162
return this.__customRoot;
163163
}
164164

@@ -174,7 +174,7 @@ describe('renderer', () => {
174174
beforeEach(async () => {
175175
overlay = fixtureSync('<custom-root-overlay></custom-root-overlay>');
176176
await nextRender();
177-
root = overlay._contentRoot;
177+
root = overlay._rendererRoot;
178178
content = document.createElement('p');
179179
content.textContent = 'renderer-content';
180180
});

packages/overlay/test/restore-focus.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ describe('custom content root', () => {
193193
get _contentRoot() {
194194
return this.owner;
195195
}
196+
197+
get _rendererRoot() {
198+
return this.owner;
199+
}
196200
},
197201
);
198202

packages/popover/src/vaadin-popover-overlay.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ class PopoverOverlay extends PopoverOverlayMixin(
7474
return this.owner;
7575
}
7676

77+
/**
78+
* @override
79+
* @protected
80+
*/
81+
get _rendererRoot() {
82+
return this.owner;
83+
}
84+
7785
/**
7886
* Override method from OverlayFocusMixin to use owner as focus trap root
7987
* @protected

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,20 @@ export const SelectOverlayMixin = (superClass) =>
2727
}
2828

2929
/**
30-
* @override
30+
* Override method from OverlayFocusMixin to use slotted div as content root.
3131
* @protected
32+
* @override
3233
*/
3334
get _contentRoot() {
35+
return this._rendererRoot;
36+
}
37+
38+
/**
39+
* Override method from OverlayMixin to use slotted div as a renderer root.
40+
* @protected
41+
* @override
42+
*/
43+
get _rendererRoot() {
3444
if (!this.__savedRoot) {
3545
const root = document.createElement('div');
3646
root.setAttribute('slot', 'overlay');
@@ -66,7 +76,7 @@ export const SelectOverlayMixin = (superClass) =>
6676

6777
/** @protected */
6878
_getMenuElement() {
69-
return Array.from(this._contentRoot.children).find((el) => el.localName !== 'style');
79+
return Array.from(this._rendererRoot.children).find((el) => el.localName !== 'style');
7080
}
7181

7282
/** @private */

0 commit comments

Comments
 (0)