diff --git a/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.d.ts b/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.d.ts index 00088b2e8a1..064ce4885d2 100644 --- a/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.d.ts +++ b/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.d.ts @@ -5,4 +5,4 @@ */ import type { CSSResult } from 'lit'; -export const horizontalLayoutStyles: CSSResult; +export const horizontalLayoutStyles: CSSResult[]; diff --git a/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.js b/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.js index c3401ceab7f..e70405bcd55 100644 --- a/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.js +++ b/packages/horizontal-layout/src/vaadin-horizontal-layout-styles.js @@ -5,7 +5,7 @@ */ import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; -export const horizontalLayoutStyles = css` +export const baseStyles = css` :host { display: flex; box-sizing: border-box; @@ -28,3 +28,21 @@ export const horizontalLayoutStyles = css` gap: 1em; } `; + +// Layout improvements are part of a feature for Flow users where children that have been configured to use full size +// using `HasSize.setSizeFull()` and others, get additional styles so that they effectively take the remaining space in +// the layout, rather than explicitly use 100% width/height. The respective data attributes are set by Flow's `HasSize` +// class. +const enableLayoutImprovements = window.Vaadin.featureFlags.layoutComponentImprovements; +const layoutImprovementStyles = css` + ::slotted([data-width-full]) { + flex: 1; + } + + ::slotted(vaadin-horizontal-layout[data-width-full]), + ::slotted(vaadin-vertical-layout[data-width-full]) { + min-width: 0; + } +`; + +export const horizontalLayoutStyles = enableLayoutImprovements ? [baseStyles, layoutImprovementStyles] : [baseStyles]; diff --git a/packages/horizontal-layout/test/enable-layout-improvements.js b/packages/horizontal-layout/test/enable-layout-improvements.js new file mode 100644 index 00000000000..ffbf764e560 --- /dev/null +++ b/packages/horizontal-layout/test/enable-layout-improvements.js @@ -0,0 +1,3 @@ +window.Vaadin ??= {}; +window.Vaadin.featureFlags ??= {}; +window.Vaadin.featureFlags.layoutComponentImprovements = true; diff --git a/packages/horizontal-layout/test/horizontal-layout.common.js b/packages/horizontal-layout/test/horizontal-layout.common.js index d1a99bcf16d..3ba80dc88a5 100644 --- a/packages/horizontal-layout/test/horizontal-layout.common.js +++ b/packages/horizontal-layout/test/horizontal-layout.common.js @@ -110,4 +110,52 @@ describe('vaadin-horizontal-layout', () => { expect(wrapper.scrollWidth).to.equal(200); }); }); + + describe('layout improvements disabled', () => { + let layout, children; + + describe('flex', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should not set flex on any children', () => { + children.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('0 1 auto'); + }); + }); + }); + + describe('min-width', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+ + + + + + +
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should not set min-width on any children', () => { + children.forEach((child) => { + expect(getComputedStyle(child).minWidth).to.equal('auto'); + }); + }); + }); + }); }); diff --git a/packages/horizontal-layout/test/layout-improvements.test.js b/packages/horizontal-layout/test/layout-improvements.test.js new file mode 100644 index 00000000000..43a9bca528f --- /dev/null +++ b/packages/horizontal-layout/test/layout-improvements.test.js @@ -0,0 +1,67 @@ +import { expect } from '@vaadin/chai-plugins'; +import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; +import './enable-layout-improvements.js'; +import '../vaadin-horizontal-layout.js'; + +describe('layout improvements enabled', () => { + let layout, children; + + describe('flex', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should set flex on full width children only', () => { + const fullWidthChildren = children.filter((child) => child.hasAttribute('data-width-full')); + const remainingChildren = children.filter((child) => !fullWidthChildren.includes(child)); + + fullWidthChildren.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('1 1 0%'); + }); + remainingChildren.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('0 1 auto'); + }); + }); + }); + + describe('min-width', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+ + + + + + +
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should set min-width on layout components with full width only', () => { + const layoutChildren = children.filter( + (child) => child.localName.endsWith('layout') && child.hasAttribute('data-width-full'), + ); + const remainingChildren = children.filter((child) => !layoutChildren.includes(child)); + + layoutChildren.forEach((child) => { + expect(getComputedStyle(child).minWidth).to.equal('0px'); + }); + + remainingChildren.forEach((child) => { + expect(getComputedStyle(child).minWidth).to.equal('auto'); + }); + }); + }); +}); diff --git a/packages/vertical-layout/src/vaadin-vertical-layout-styles.d.ts b/packages/vertical-layout/src/vaadin-vertical-layout-styles.d.ts index 570e7aedb24..b3e06d39b72 100644 --- a/packages/vertical-layout/src/vaadin-vertical-layout-styles.d.ts +++ b/packages/vertical-layout/src/vaadin-vertical-layout-styles.d.ts @@ -5,4 +5,4 @@ */ import type { CSSResult } from 'lit'; -export const verticalLayoutStyles: CSSResult; +export const verticalLayoutStyles: CSSResult[]; diff --git a/packages/vertical-layout/src/vaadin-vertical-layout-styles.js b/packages/vertical-layout/src/vaadin-vertical-layout-styles.js index f345c8f98d4..498f313b430 100644 --- a/packages/vertical-layout/src/vaadin-vertical-layout-styles.js +++ b/packages/vertical-layout/src/vaadin-vertical-layout-styles.js @@ -5,7 +5,7 @@ */ import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; -export const verticalLayoutStyles = css` +export const baseStyles = css` :host { display: flex; flex-direction: column; @@ -30,3 +30,21 @@ export const verticalLayoutStyles = css` gap: 1em; } `; + +// Layout improvements are part of a feature for Flow users where children that have been configured to use full size +// using `HasSize.setSizeFull()` and others, get additional styles so that they effectively take the remaining space in +// the layout, rather than explicitly use 100% width/height. The respective data attributes are set by Flow's `HasSize` +// class. +const enableLayoutImprovements = window.Vaadin.featureFlags.layoutComponentImprovements; +const layoutImprovementStyles = css` + ::slotted([data-height-full]) { + flex: 1; + } + + ::slotted(vaadin-horizontal-layout[data-height-full]), + ::slotted(vaadin-vertical-layout[data-height-full]) { + min-height: 0; + } +`; + +export const verticalLayoutStyles = enableLayoutImprovements ? [baseStyles, layoutImprovementStyles] : [baseStyles]; diff --git a/packages/vertical-layout/test/enable-layout-improvements.js b/packages/vertical-layout/test/enable-layout-improvements.js new file mode 100644 index 00000000000..ffbf764e560 --- /dev/null +++ b/packages/vertical-layout/test/enable-layout-improvements.js @@ -0,0 +1,3 @@ +window.Vaadin ??= {}; +window.Vaadin.featureFlags ??= {}; +window.Vaadin.featureFlags.layoutComponentImprovements = true; diff --git a/packages/vertical-layout/test/layout-improvements.test.js b/packages/vertical-layout/test/layout-improvements.test.js new file mode 100644 index 00000000000..c4d7a11d511 --- /dev/null +++ b/packages/vertical-layout/test/layout-improvements.test.js @@ -0,0 +1,67 @@ +import { expect } from '@vaadin/chai-plugins'; +import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; +import './enable-layout-improvements.js'; +import '../vaadin-vertical-layout.js'; + +describe('layout improvements enabled', () => { + let layout, children; + + describe('flex', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should set flex on full height children only', () => { + const fullHeightChildren = children.filter((child) => child.hasAttribute('data-height-full')); + const remainingChildren = children.filter((child) => !fullHeightChildren.includes(child)); + + fullHeightChildren.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('1 1 0%'); + }); + remainingChildren.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('0 1 auto'); + }); + }); + }); + + describe('min-height', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+ + + + + + +
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should set min-height on layout components with full height only', () => { + const layoutChildren = children.filter( + (child) => child.localName.endsWith('layout') && child.hasAttribute('data-height-full'), + ); + const remainingChildren = children.filter((child) => !layoutChildren.includes(child)); + + layoutChildren.forEach((child) => { + expect(getComputedStyle(child).minHeight).to.equal('0px'); + }); + + remainingChildren.forEach((child) => { + expect(getComputedStyle(child).minHeight).to.equal('auto'); + }); + }); + }); +}); diff --git a/packages/vertical-layout/test/vertical-layout.common.js b/packages/vertical-layout/test/vertical-layout.common.js index ddad2bfae8c..96ef359cd31 100644 --- a/packages/vertical-layout/test/vertical-layout.common.js +++ b/packages/vertical-layout/test/vertical-layout.common.js @@ -111,4 +111,52 @@ describe('vaadin-vertical-layout', () => { expect(wrapper.scrollHeight).to.equal(200); }); }); + + describe('layout improvements disabled', () => { + let layout, children; + + describe('flex', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should not set flex on any children', () => { + children.forEach((child) => { + expect(getComputedStyle(child).flex).to.equal('0 1 auto'); + }); + }); + }); + + describe('min-height', () => { + beforeEach(async () => { + layout = fixtureSync(` + +
+
+ + + + + + +
+ `); + children = Array.from(layout.children); + await nextFrame(); + }); + + it('should not set min-height on any children', () => { + children.forEach((child) => { + expect(getComputedStyle(child).minHeight).to.equal('auto'); + }); + }); + }); + }); });