Skip to content

Commit aad0c3e

Browse files
authored
refactor: set overflow attribute on dialog overlay content change (#9903)
1 parent 9f70cc5 commit aad0c3e

File tree

6 files changed

+240
-165
lines changed

6 files changed

+240
-165
lines changed

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,21 @@ export const DialogOverlayMixin = (superClass) =>
6868

6969
// Update overflow attribute on resize
7070
this.__resizeObserver = new ResizeObserver(() => {
71-
this.__updateOverflow();
71+
requestAnimationFrame(() => {
72+
this.__updateOverflow();
73+
});
7274
});
7375
this.__resizeObserver.observe(this.$.resizerContainer);
7476

7577
// Update overflow attribute on scroll
7678
this.$.content.addEventListener('scroll', () => {
7779
this.__updateOverflow();
7880
});
81+
82+
// Update overflow attribute on content change
83+
this.shadowRoot.addEventListener('slotchange', () => {
84+
this.__updateOverflow();
85+
});
7986
}
8087

8188
/** @private */
@@ -230,18 +237,14 @@ export const DialogOverlayMixin = (superClass) =>
230237
__updateOverflow() {
231238
let overflow = '';
232239

233-
// Only set "overflow" attribute if the dialog has a header, title or footer.
234-
// Check for state attributes as extending components might not use renderers.
235-
if (this.hasAttribute('has-header') || this.hasAttribute('has-footer') || this.headerTitle) {
236-
const content = this.$.content;
240+
const content = this.$.content;
237241

238-
if (content.scrollTop > 0) {
239-
overflow += ' top';
240-
}
242+
if (content.scrollTop > 0) {
243+
overflow += ' top';
244+
}
241245

242-
if (content.scrollTop < content.scrollHeight - content.clientHeight) {
243-
overflow += ' bottom';
244-
}
246+
if (content.scrollTop < content.scrollHeight - content.clientHeight) {
247+
overflow += ' bottom';
245248
}
246249

247250
const value = overflow.trim();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ describe('overflowing content', () => {
842842
div.style.maxWidth = '300px';
843843
div.style.overflow = 'auto';
844844
div.textContent = Array(100).join('Lorem ipsum dolor sit amet');
845-
overlay.appendChild(div);
845+
dialog.appendChild(div);
846846
// Emulate removing "pointer-events: none"
847847
overlayPart.setAttribute('style', '');
848848
expect(overlayPart.offsetHeight).to.equal(container.offsetHeight);
@@ -851,7 +851,7 @@ describe('overflowing content', () => {
851851
it('should not reset scroll position on resize', async () => {
852852
const div = document.createElement('div');
853853
div.textContent = Array(100).join('Lorem ipsum dolor sit amet');
854-
overlay.appendChild(div);
854+
dialog.appendChild(div);
855855
dialog.$.overlay.setBounds({ height: 200 });
856856
await nextFrame();
857857
overlay.$.content.style.padding = '20px';

packages/dialog/test/header-footer.test.js

Lines changed: 1 addition & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from '@vaadin/chai-plugins';
2-
import { fixtureSync, nextRender, nextResize, nextUpdate } from '@vaadin/testing-helpers';
2+
import { fixtureSync, nextRender, nextUpdate } from '@vaadin/testing-helpers';
33
import sinon from 'sinon';
44
import '../src/vaadin-dialog.js';
55
import { createRenderer } from './helpers.js';
@@ -482,137 +482,6 @@ describe('header/footer feature', () => {
482482
expect(getComputedStyle(headerPart).display).to.be.equal('none');
483483
});
484484
});
485-
486-
describe('overflow attribute', () => {
487-
let content, headerHeight, footerHeight, contentHeight;
488-
489-
beforeEach(async () => {
490-
dialog.headerRenderer = createRenderer('Header');
491-
dialog.footerRenderer = createRenderer('Footer');
492-
dialog.renderer = createRenderer(Array(10).join('Lorem ipsum dolor sit amet\n'));
493-
dialog.resizable = true;
494-
dialog.opened = true;
495-
await nextRender();
496-
content = overlay.$.content;
497-
overlay.style.maxWidth = '300px';
498-
499-
headerHeight = overlay.shadowRoot.querySelector('[part=header]').offsetHeight;
500-
footerHeight = overlay.shadowRoot.querySelector('[part=footer]').offsetHeight;
501-
contentHeight = overlay.shadowRoot.querySelector('[part=content]').offsetHeight;
502-
});
503-
504-
describe('resize', () => {
505-
it('should not set overflow attribute when content has no scrollbar', () => {
506-
expect(dialog.hasAttribute('overflow')).to.be.false;
507-
expect(overlay.hasAttribute('overflow')).to.be.false;
508-
});
509-
510-
it('should set overflow attribute when scrollbar appears on resize', async () => {
511-
overlay.style.maxHeight = `${contentHeight}px`;
512-
await nextResize(overlay);
513-
expect(dialog.getAttribute('overflow')).to.equal('bottom');
514-
expect(overlay.getAttribute('overflow')).to.equal('bottom');
515-
});
516-
517-
it('should remove overflow attribute when header renderer is removed', async () => {
518-
overlay.style.maxHeight = `${contentHeight + footerHeight}px`;
519-
await nextResize(overlay);
520-
expect(dialog.hasAttribute('overflow')).to.be.true;
521-
expect(overlay.hasAttribute('overflow')).to.be.true;
522-
523-
dialog.headerRenderer = null;
524-
await nextUpdate(dialog);
525-
expect(dialog.hasAttribute('overflow')).to.be.false;
526-
expect(overlay.hasAttribute('overflow')).to.be.false;
527-
});
528-
529-
it('should remove overflow attribute when footer renderer is removed', async () => {
530-
overlay.style.maxHeight = `${contentHeight + headerHeight}px`;
531-
await nextResize(overlay);
532-
expect(dialog.hasAttribute('overflow')).to.be.true;
533-
expect(overlay.hasAttribute('overflow')).to.be.true;
534-
535-
dialog.footerRenderer = null;
536-
await nextUpdate(dialog);
537-
expect(dialog.hasAttribute('overflow')).to.be.false;
538-
expect(overlay.hasAttribute('overflow')).to.be.false;
539-
});
540-
541-
it('should set overflow attribute when header title property is set', async () => {
542-
dialog.headerRenderer = null;
543-
dialog.footerRenderer = null;
544-
await nextUpdate(dialog);
545-
546-
overlay.style.maxHeight = `${contentHeight}px`;
547-
await nextResize(overlay);
548-
expect(dialog.hasAttribute('overflow')).to.be.false;
549-
expect(overlay.hasAttribute('overflow')).to.be.false;
550-
551-
dialog.headerTitle = 'Title';
552-
await nextUpdate(dialog);
553-
expect(dialog.getAttribute('overflow')).to.equal('bottom');
554-
expect(overlay.getAttribute('overflow')).to.equal('bottom');
555-
});
556-
557-
it('should remove overflow attribute when header title is removed', async () => {
558-
dialog.headerRenderer = null;
559-
dialog.footerRenderer = null;
560-
dialog.headerTitle = 'Title';
561-
await nextUpdate(dialog);
562-
563-
overlay.style.maxHeight = `${contentHeight}px`;
564-
await nextResize(overlay);
565-
expect(dialog.hasAttribute('overflow')).to.be.true;
566-
expect(overlay.hasAttribute('overflow')).to.be.true;
567-
568-
dialog.headerTitle = null;
569-
await nextUpdate(dialog);
570-
expect(dialog.hasAttribute('overflow')).to.be.false;
571-
expect(overlay.hasAttribute('overflow')).to.be.false;
572-
});
573-
574-
it('should remove overflow attribute if no header, footer or title is set', async () => {
575-
dialog.headerTitle = 'Title';
576-
overlay.style.maxHeight = `${contentHeight}px`;
577-
await nextResize(overlay);
578-
579-
dialog.headerRenderer = null;
580-
dialog.footerRenderer = null;
581-
dialog.headerTitle = null;
582-
await nextUpdate(dialog);
583-
expect(dialog.hasAttribute('overflow')).to.be.false;
584-
expect(overlay.hasAttribute('overflow')).to.be.false;
585-
});
586-
});
587-
588-
describe('scroll', () => {
589-
beforeEach(async () => {
590-
dialog.renderer = createRenderer(Array(100).join('Lorem ipsum dolor sit amet\n'));
591-
await nextUpdate(dialog);
592-
});
593-
594-
it('should set overflow to "bottom" when scrollbar appears after re-render', () => {
595-
expect(dialog.getAttribute('overflow')).to.equal('bottom');
596-
expect(overlay.getAttribute('overflow')).to.equal('bottom');
597-
});
598-
599-
it('should update overflow to "top bottom" on partial content scroll', () => {
600-
content.scrollTop += 200;
601-
content.dispatchEvent(new CustomEvent('scroll'));
602-
603-
expect(dialog.getAttribute('overflow')).to.equal('top bottom');
604-
expect(overlay.getAttribute('overflow')).to.equal('top bottom');
605-
});
606-
607-
it('should update overflow to "top" when content is fully scrolled', () => {
608-
content.scrollTop += content.scrollHeight - content.clientHeight;
609-
content.dispatchEvent(new CustomEvent('scroll'));
610-
611-
expect(dialog.getAttribute('overflow')).to.equal('top');
612-
expect(overlay.getAttribute('overflow')).to.equal('top');
613-
});
614-
});
615-
});
616485
});
617486

618487
describe('renderer set before attach', () => {

0 commit comments

Comments
 (0)