-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add vaadin-dashboard-layout #7653
Merged
Merged
Changes from 5 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
2283236
feat: add vaadin-dashboard-layout
tomivirkki a000898
test default min and max col width
tomivirkki a4b1870
cleanup
tomivirkki 39aa823
add comments to css properties
tomivirkki cdc7f35
test: make sure max col width is not smaller than min col width in a …
tomivirkki 557352a
remove "mixes ResizeMixin"
tomivirkki ca24c3c
change the default value for max col width to 1fr
tomivirkki 93145bf
use min/max col width values from ac
tomivirkki d4fd49a
update default values
tomivirkki 1c48434
Update packages/dashboard/test/dashboard-layout.test.ts
tomivirkki 00c1537
fix typo
tomivirkki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Dashboard layout</title> | ||
<script type="module" src="./common.js"></script> | ||
|
||
<script type="module"> | ||
import '@vaadin/dashboard/vaadin-dashboard-layout.js'; | ||
</script> | ||
|
||
<style> | ||
vaadin-dashboard-layout div { | ||
background-color: #f5f5f5; | ||
border: 1px solid #e0e0e0; | ||
border-radius: 4px; | ||
padding: 1em; | ||
text-align: center; | ||
margin: 0.5em; | ||
box-sizing: border-box; | ||
height: 100px; | ||
} | ||
|
||
vaadin-dashboard-layout { | ||
--vaadin-dashboard-col-min-width: 300px; | ||
--vaadin-dashboard-col-max-width: 500px; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<vaadin-dashboard-layout> | ||
<div>Item 0</div> | ||
<div>Item 1</div> | ||
<div>Item 2</div> | ||
<div>Item 3</div> | ||
<div>Item 4</div> | ||
</vaadin-dashboard-layout> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2000 - 2024 Vaadin Ltd. | ||
* | ||
* This program is available under Vaadin Commercial License and Service Terms. | ||
* | ||
* | ||
* See https://vaadin.com/commercial-license-and-service-terms for the full | ||
* license. | ||
*/ | ||
import type { Constructor } from '@open-wc/dedupe-mixin'; | ||
|
||
/** | ||
* A mixin to enable the dashboard layout functionality. | ||
*/ | ||
export declare function DashboardLayoutMixin<T extends Constructor<HTMLElement>>( | ||
base: T, | ||
): Constructor<DashboardLayoutMixinClass> & T; | ||
|
||
export declare class DashboardLayoutMixinClass {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2000 - 2024 Vaadin Ltd. | ||
* | ||
* This program is available under Vaadin Commercial License and Service Terms. | ||
* | ||
* | ||
* See https://vaadin.com/commercial-license-and-service-terms for the full | ||
* license. | ||
*/ | ||
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 { | ||
static get styles() { | ||
return css` | ||
:host { | ||
display: grid; | ||
/* Default min and max column widths */ | ||
--_vaadin-dashboard-default-col-min-width: 200px; | ||
--_vaadin-dashboard-default-col-max-width: 400px; | ||
/* Effective min and max column widths */ | ||
--_vaadin-dashboard-col-min-width: var( | ||
--vaadin-dashboard-col-min-width, | ||
var(--_vaadin-dashboard-default-col-min-width) | ||
); | ||
--_vaadin-dashboard-col-max-width: var( | ||
--vaadin-dashboard-col-max-width, | ||
var(--_vaadin-dashboard-default-col-max-width) | ||
); | ||
|
||
grid-template-columns: repeat( | ||
auto-fill, | ||
minmax(var(--_vaadin-dashboard-col-min-width), var(--_vaadin-dashboard-col-max-width)) | ||
); | ||
} | ||
`; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2000 - 2024 Vaadin Ltd. | ||
* | ||
* This program is available under Vaadin Commercial License and Service Terms. | ||
* | ||
* | ||
* See https://vaadin.com/commercial-license-and-service-terms for the full | ||
* license. | ||
*/ | ||
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
|
||
/** | ||
* A responsive, grid-based dashboard layout component | ||
*/ | ||
declare class DashboardLayout extends ElementMixin(ThemableMixin(HTMLElement)) {} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'vaadin-dashboard-layout': DashboardLayout; | ||
} | ||
} | ||
|
||
export { DashboardLayout }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2000 - 2024 Vaadin Ltd. | ||
* | ||
* This program is available under Vaadin Commercial License and Service Terms. | ||
* | ||
* | ||
* See https://vaadin.com/commercial-license-and-service-terms for the full | ||
* license. | ||
*/ | ||
import { html, LitElement } from 'lit'; | ||
import { defineCustomElement } from '@vaadin/component-base/src/define.js'; | ||
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; | ||
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import { DashboardLayoutMixin } from './vaadin-dashboard-layout-mixin.js'; | ||
|
||
/** | ||
* A responsive, grid-based dashboard layout component | ||
* | ||
* @customElement | ||
* @extends HTMLElement | ||
* @mixes DashboardLayoutMixin | ||
* @mixes ElementMixin | ||
* @mixes ThemableMixin | ||
*/ | ||
class DashboardLayout extends DashboardLayoutMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) { | ||
static get is() { | ||
return 'vaadin-dashboard-layout'; | ||
} | ||
|
||
/** @protected */ | ||
render() { | ||
return html`<slot></slot>`; | ||
} | ||
} | ||
|
||
defineCustomElement(DashboardLayout); | ||
|
||
export { DashboardLayout }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import { expect } from '@vaadin/chai-plugins'; | ||
import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; | ||
import '../vaadin-dashboard-layout.js'; | ||
import type { DashboardLayout } from '../vaadin-dashboard-layout.js'; | ||
import { | ||
getColumnWidths, | ||
getElementFromCell, | ||
setGap, | ||
setMaximumColumnWidth, | ||
setMinimumColumnWidth, | ||
} from './helpers.js'; | ||
|
||
/** | ||
* Validates the given grid layout. | ||
* | ||
* This function iterates through a number matrix representing the IDs of | ||
* the items in the layout, and checks if the elements in the corresponding | ||
* cells of the grid match the expected IDs. | ||
* | ||
* For example, the following layout would expect a grid with two columns | ||
* and three rows, where the first row has one element with ID "item-0" spanning | ||
* two columns, and the second row has two elements with IDs "item-1" and "item-2" | ||
* where the first one spans two rows, and the last cell in the third row has | ||
* an element with ID "item-3": | ||
* | ||
* ``` | ||
* [ | ||
* [0, 0], | ||
* [1, 2], | ||
* [1, 3] | ||
* ] | ||
* ``` | ||
*/ | ||
function expectLayout(dashboard: DashboardLayout, layout: number[][]) { | ||
layout.forEach((row, rowIndex) => { | ||
row.forEach((itemId, columnIndex) => { | ||
const element = getElementFromCell(dashboard, rowIndex, columnIndex); | ||
if (!element) { | ||
expect(itemId).to.be.undefined; | ||
} else { | ||
expect(element.id).to.equal(`item-${itemId}`); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
describe('dashboard layout', () => { | ||
let dashboard: DashboardLayout; | ||
const columnWidth = 100; | ||
|
||
beforeEach(async () => { | ||
dashboard = fixtureSync(` | ||
<vaadin-dashboard-layout> | ||
<div id="item-0">Item 0</div> | ||
<div id="item-1">Item 1</div> | ||
</vaadin-dashboard-layout> | ||
`); | ||
// Disable gap between items in these tests | ||
setGap(dashboard, 0); | ||
// Set the column width to a fixed value | ||
setMinimumColumnWidth(dashboard, columnWidth); | ||
setMaximumColumnWidth(dashboard, columnWidth); | ||
// Make the dashboard wide enough to fit all items on a single row | ||
dashboard.style.width = `${columnWidth * dashboard.childElementCount}px`; | ||
|
||
await nextFrame(); | ||
|
||
expect(getColumnWidths(dashboard)).to.eql([columnWidth, columnWidth]); | ||
/* prettier-ignore */ | ||
expectLayout(dashboard, [ | ||
[0, 1], | ||
]); | ||
}); | ||
|
||
it('should be responsive', () => { | ||
// Narrow down the component to fit one column | ||
dashboard.style.width = `${columnWidth}px`; | ||
|
||
/* prettier-ignore */ | ||
expectLayout(dashboard, [ | ||
[0], | ||
[1], | ||
]); | ||
}); | ||
|
||
describe('minimum column width', () => { | ||
it('should have a default minimum column width', () => { | ||
// Clear the minimum column width used in the tests | ||
setMinimumColumnWidth(dashboard, undefined); | ||
// Narrow down the component to have the width of 0 | ||
dashboard.style.width = '0'; | ||
// Expect the column width to equal the default minimum column width | ||
expect(getColumnWidths(dashboard)).to.eql([200]); | ||
}); | ||
|
||
it('should have one overflown column if narrowed below miminum column width', () => { | ||
tomivirkki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Narrow down the component to have the width of half a column | ||
dashboard.style.width = `${columnWidth / 2}px`; | ||
// Expect the column width to still be the same (overflown) | ||
expect(getColumnWidths(dashboard)).to.eql([columnWidth]); | ||
}); | ||
|
||
it('should not overflow if narrowed to the minimum column width', () => { | ||
// Set the min column width to half of the column width | ||
setMinimumColumnWidth(dashboard, columnWidth / 2); | ||
// Narrow down the component to have the width of half a column | ||
dashboard.style.width = `${columnWidth / 2}px`; | ||
// Expect the column width to equal the min column width | ||
expect(getColumnWidths(dashboard)).to.eql([columnWidth / 2]); | ||
}); | ||
|
||
it('should have one wide column with large minimum column width', () => { | ||
setMaximumColumnWidth(dashboard, columnWidth * 2); | ||
// Set the min column width to be twice as wide | ||
setMinimumColumnWidth(dashboard, columnWidth * 2); | ||
// Expect there to only be one column with twice the width | ||
expect(getColumnWidths(dashboard)).to.eql([columnWidth * 2]); | ||
/* prettier-ignore */ | ||
expectLayout(dashboard, [ | ||
[0], | ||
[1], | ||
]); | ||
}); | ||
}); | ||
|
||
describe('maximum column width', () => { | ||
it('should have a default maximum column width', () => { | ||
// Clear the maximum column width used in the tests | ||
setMaximumColumnWidth(dashboard, undefined); | ||
// Widen the component | ||
dashboard.style.width = '1000px'; | ||
// Expect the column width to equal the default maximum column width | ||
expect(getColumnWidths(dashboard)[0]).to.eql(400); | ||
}); | ||
|
||
it('should have one wide column with large maximum column width', () => { | ||
// Allow the column to be twice as wide | ||
setMaximumColumnWidth(dashboard, columnWidth * 2); | ||
// Expect there to only be one column with twice the width | ||
expect(getColumnWidths(dashboard)).to.eql([columnWidth * 2]); | ||
/* prettier-ignore */ | ||
expectLayout(dashboard, [ | ||
[0], | ||
[1], | ||
]); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no
ResizeMixin
used here, so this line should be probably removed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, removed for now. ResizeMixin is to be added in a separate PR.