diff --git a/dev/dashboard-layout.html b/dev/dashboard-layout.html index c02fbc7f75..97e34f781b 100644 --- a/dev/dashboard-layout.html +++ b/dev/dashboard-layout.html @@ -24,6 +24,7 @@ vaadin-dashboard-layout { --vaadin-dashboard-col-min-width: 300px; --vaadin-dashboard-col-max-width: 500px; + --vaadin-dashboard-row-min-height: 300px; --vaadin-dashboard-gap: 20px; --vaadin-dashboard-col-max-count: 3; } diff --git a/dev/dashboard.html b/dev/dashboard.html index 017abfb110..1517f2d513 100644 --- a/dev/dashboard.html +++ b/dev/dashboard.html @@ -18,6 +18,7 @@ vaadin-dashboard { --vaadin-dashboard-col-min-width: 300px; --vaadin-dashboard-col-max-width: 500px; + --vaadin-dashboard-row-min-height: 300px; --vaadin-dashboard-gap: 20px; --vaadin-dashboard-col-max-count: 3; } diff --git a/packages/dashboard/src/vaadin-dashboard-layout-mixin.js b/packages/dashboard/src/vaadin-dashboard-layout-mixin.js index 5fe15dd7ef..bca569d49e 100644 --- a/packages/dashboard/src/vaadin-dashboard-layout-mixin.js +++ b/packages/dashboard/src/vaadin-dashboard-layout-mixin.js @@ -54,6 +54,9 @@ export const DashboardLayoutMixin = (superClass) => var(--_vaadin-dashboard-col-max-count) ); + /* Effective row height */ + --_vaadin-dashboard-row-height: minmax(var(--vaadin-dashboard-row-min-height, auto), auto); + display: grid; overflow: auto; height: 100%; @@ -63,6 +66,8 @@ export const DashboardLayoutMixin = (superClass) => minmax(var(--_vaadin-dashboard-col-min-width), var(--_vaadin-dashboard-col-max-width)) ); + grid-auto-rows: var(--_vaadin-dashboard-row-height); + gap: var(--vaadin-dashboard-gap, 1rem); } diff --git a/packages/dashboard/src/vaadin-dashboard-section.js b/packages/dashboard/src/vaadin-dashboard-section.js index 21e5679066..409a2f9926 100644 --- a/packages/dashboard/src/vaadin-dashboard-section.js +++ b/packages/dashboard/src/vaadin-dashboard-section.js @@ -37,6 +37,13 @@ class DashboardSection extends ControllerMixin(ElementMixin(PolylitMixin(LitElem --_vaadin-dashboard-section-column: 1 / calc(var(--_vaadin-dashboard-effective-col-count) + 1); grid-column: var(--_vaadin-dashboard-section-column) !important; gap: var(--vaadin-dashboard-gap, 1rem); + /* Dashbaord section header height */ + --_vaadin-dashboard-section-header-height: minmax(0, auto); + grid-template-rows: var(--_vaadin-dashboard-section-header-height) repeat( + auto-fill, + var(--_vaadin-dashboard-row-height) + ); + grid-auto-rows: var(--_vaadin-dashboard-row-height); } :host([hidden]) { diff --git a/packages/dashboard/test/dashboard-layout.test.ts b/packages/dashboard/test/dashboard-layout.test.ts index be32d0850b..3bee75cfc2 100644 --- a/packages/dashboard/test/dashboard-layout.test.ts +++ b/packages/dashboard/test/dashboard-layout.test.ts @@ -3,6 +3,7 @@ import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; import '../vaadin-dashboard-layout.js'; import '../vaadin-dashboard-section.js'; import type { DashboardLayout } from '../vaadin-dashboard-layout.js'; +import type { DashboardSection } from '../vaadin-dashboard-section.js'; import { getColumnWidths, getElementFromCell, @@ -13,6 +14,7 @@ import { setMaximumColumnCount, setMaximumColumnWidth, setMinimumColumnWidth, + setMinimumRowHeight, } from './helpers.js'; /** @@ -199,6 +201,33 @@ describe('dashboard layout', () => { }); }); + describe('minimum row height', () => { + const rowHeight = 100; + + it('should have the row height of the highest wigdet on a row by default', () => { + childElements[0].style.height = `${rowHeight}px`; + childElements[1].style.height = '50px'; + expect(getRowHeights(dashboard)).to.eql([rowHeight]); + }); + + it('should set a minimum row height', () => { + setMinimumRowHeight(dashboard, rowHeight); + expect(getRowHeights(dashboard)).to.eql([rowHeight]); + }); + + it('should not constrain widgets to the minumum row height', () => { + childElements[0].style.height = `${rowHeight * 2}px`; + setMinimumRowHeight(dashboard, rowHeight); + expect(getRowHeights(dashboard)).to.eql([rowHeight * 2]); + }); + + it('should use minimum row height for all rows', () => { + dashboard.style.width = `${columnWidth}px`; + setMinimumRowHeight(dashboard, rowHeight); + expect(getRowHeights(dashboard)).to.eql([rowHeight, rowHeight]); + }); + }); + describe('column span', () => { it('should span multiple columns', async () => { setColspan(childElements[0], 2); @@ -365,9 +394,11 @@ describe('dashboard layout', () => { }); describe('section', () => { + let section: DashboardSection; + beforeEach(async () => { - const section = fixtureSync(` - + section = fixtureSync(` +
Section item 2
Section item 3
@@ -434,6 +465,27 @@ describe('dashboard layout', () => { ]); }); + it('should use minimum row height for all section rows', async () => { + dashboard.style.width = `${columnWidth}px`; + setMinimumRowHeight(dashboard, 300); + await nextFrame(); + + expect(childElements[2].offsetHeight).to.eql(300); + expect(childElements[3].offsetHeight).to.eql(300); + }); + + it('should not use minimum row height for section header row', async () => { + const title = section.querySelector('[slot="title"]')!; + title.style.height = '100%'; + + const titleHeight = title.offsetHeight; + setMinimumRowHeight(dashboard, 300); + await nextFrame(); + + const newTitleHeight = title.offsetHeight; + expect(newTitleHeight).to.eql(titleHeight); + }); + describe('gap', () => { it('should have a default gap', () => { // Clear the gap used in the tests diff --git a/packages/dashboard/test/helpers.ts b/packages/dashboard/test/helpers.ts index cd16fedddc..75662401ca 100644 --- a/packages/dashboard/test/helpers.ts +++ b/packages/dashboard/test/helpers.ts @@ -98,3 +98,10 @@ export function setGap(dashboard: HTMLElement, gap?: number): void { export function setMaximumColumnCount(dashboard: HTMLElement, count?: number): void { dashboard.style.setProperty('--vaadin-dashboard-col-max-count', count !== undefined ? `${count}` : null); } + +/** + * Sets the minimum row height of the dashboard. + */ +export function setMinimumRowHeight(dashboard: HTMLElement, height?: number): void { + dashboard.style.setProperty('--vaadin-dashboard-row-min-height', height !== undefined ? `${height}px` : null); +}