Skip to content

Commit

Permalink
feat: add colspan support to dashboard (#7657)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomivirkki authored Aug 16, 2024
1 parent 8864042 commit e0a2f54
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 3 deletions.
2 changes: 1 addition & 1 deletion dev/dashboard-layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<body>
<vaadin-dashboard-layout>
<div>Item 0</div>
<div>Item 1</div>
<div style="--vaadin-dashboard-item-colspan: 2">Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
Expand Down
3 changes: 2 additions & 1 deletion packages/dashboard/src/vaadin-dashboard-layout-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
* license.
*/
import type { Constructor } from '@open-wc/dedupe-mixin';
import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';

/**
* A mixin to enable the dashboard layout functionality.
*/
export declare function DashboardLayoutMixin<T extends Constructor<HTMLElement>>(
base: T,
): Constructor<DashboardLayoutMixinClass> & T;
): Constructor<DashboardLayoutMixinClass> & Constructor<ResizeMixinClass> & T;

export declare class DashboardLayoutMixinClass {}
28 changes: 27 additions & 1 deletion packages/dashboard/src/vaadin-dashboard-layout-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
* See https://vaadin.com/commercial-license-and-service-terms for the full
* license.
*/
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

/**
* A mixin to enable the dashboard layout functionality
*
* @polymerMixin
* @mixes ResizeMixin
*/
export const DashboardLayoutMixin = (superClass) =>
class DashboardLayoutMixinClass extends superClass {
class DashboardLayoutMixinClass extends ResizeMixin(superClass) {
static get styles() {
return css`
:host {
Expand All @@ -39,6 +41,30 @@ export const DashboardLayoutMixin = (superClass) =>
minmax(var(--_vaadin-dashboard-col-min-width), var(--_vaadin-dashboard-col-max-width))
);
}
::slotted(*) {
grid-column: span min(var(--vaadin-dashboard-item-colspan, 1), var(--_vaadin-dashboard-item-max-colspan));
}
`;
}

/**
* @protected
* @override
*/
_onResize() {
this.__updateItemMaxColspan();
}

/**
* @private
*/
__updateItemMaxColspan() {
// Temporarily set max colspan to 1
this.style.setProperty('--_vaadin-dashboard-item-max-colspan', 1);
// Get the effective column count with no colspans
const columnCount = getComputedStyle(this).gridTemplateColumns.split(' ').length;
// ...and set it as the new max colspan value
this.style.setProperty('--_vaadin-dashboard-item-max-colspan', columnCount);
}
};
47 changes: 47 additions & 0 deletions packages/dashboard/test/dashboard-layout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { DashboardLayout } from '../vaadin-dashboard-layout.js';
import {
getColumnWidths,
getElementFromCell,
getRowHeights,
setColspan,
setGap,
setMaximumColumnWidth,
setMinimumColumnWidth,
Expand Down Expand Up @@ -32,6 +34,9 @@ import {
* ```
*/
function expectLayout(dashboard: DashboardLayout, layout: number[][]) {
expect(getRowHeights(dashboard).length).to.eql(layout.length);
expect(getColumnWidths(dashboard).length).to.eql(layout[0].length);

layout.forEach((row, rowIndex) => {
row.forEach((itemId, columnIndex) => {
const element = getElementFromCell(dashboard, rowIndex, columnIndex);
Expand All @@ -46,6 +51,7 @@ function expectLayout(dashboard: DashboardLayout, layout: number[][]) {

describe('dashboard layout', () => {
let dashboard: DashboardLayout;
let childElements: HTMLElement[];
const columnWidth = 100;
const remValue = parseFloat(getComputedStyle(document.documentElement).fontSize);

Expand All @@ -56,6 +62,7 @@ describe('dashboard layout', () => {
<div id="item-1">Item 1</div>
</vaadin-dashboard-layout>
`);
childElements = [...dashboard.children] as HTMLElement[];
// Disable gap between items in these tests
setGap(dashboard, 0);
// Set the column width to a fixed value
Expand Down Expand Up @@ -152,4 +159,44 @@ describe('dashboard layout', () => {
]);
});
});

describe('column span', () => {
it('should span multiple columns', async () => {
setColspan(childElements[0], 2);
await nextFrame();

/* prettier-ignore */
expectLayout(dashboard, [
[0, 0],
[1],
]);
});

it('should be capped to currently available columns', async () => {
setColspan(childElements[0], 2);
await nextFrame();

dashboard.style.width = `${columnWidth}px`;
await nextFrame();

/* prettier-ignore */
expectLayout(dashboard, [
[0],
[1],
]);
});

it('should span multiple columns on a single row', async () => {
setColspan(childElements[0], 2);
await nextFrame();

dashboard.style.width = `${columnWidth * 3}px`;
await nextFrame();

/* prettier-ignore */
expectLayout(dashboard, [
[0, 0, 1],
]);
});
});
});
7 changes: 7 additions & 0 deletions packages/dashboard/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export function setMaximumColumnWidth(dashboard: HTMLElement, width?: number): v
dashboard.style.setProperty('--vaadin-dashboard-col-max-width', width !== undefined ? `${width}px` : null);
}

/**
* Sets the column span of the element
*/
export function setColspan(element: HTMLElement, colspan?: number): void {
element.style.setProperty('--vaadin-dashboard-item-colspan', colspan !== undefined ? `${colspan}` : null);
}

/**
* Sets the gap between the cells of the dashboard.
*/
Expand Down

0 comments on commit e0a2f54

Please sign in to comment.