-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
87 additions
and
63 deletions.
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 |
---|---|---|
|
@@ -12,7 +12,7 @@ version: since:com.vaadin:[email protected] | |
|
||
|
||
= Dashboard | ||
:experimental: | ||
:toclevels: 2 | ||
|
||
// tag::description[] | ||
A component for building static dashboard layouts and dynamic, user-configurable dashboards. | ||
|
@@ -25,7 +25,7 @@ include::{articles}/_commercial-banner.adoc[opts=optional] | |
:feature-flag: com.vaadin.experimental.dashboardComponent | ||
include::{articles}/_preview-banner.adoc[opts=optional] | ||
|
||
[.example] | ||
[.example.tall] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -49,29 +49,40 @@ include::{root}/frontend/demo/component/dashboard/dashboard-basic.ts[render,tags | |
endif::[] | ||
-- | ||
|
||
Widgets are placed in columns and rows automatically, in the order supplied, based on the Dashboard's width and the column configuration. As the Dashboard's width changes, the number of columns is automatically adjusted based on their configured minimum and maximum width, and the widget positions are adjusted accordingly. Widgets can not be explicitly placed in a particular column or row. | ||
|
||
The Dashboard provides built-in vertical scrolling, provided that its height has been specified. | ||
== Key Features | ||
|
||
The Dashboard component can be used in two ways: | ||
[.term-width-auto] | ||
*Static & Dynamic Dashboards*:: | ||
+ | ||
*<<#static-dashboards,Static>>*: | ||
You define a dashboard and its widgets declaratively or imperatively. The React and Web Components for this are `<DashboardLayout>` & `<DashboardWidget>` and `<vaadin-dashboard-layout>` & `<vaadin-dashboard-widget>` respectively. | ||
+ | ||
*<<#dynamic-dashboards,Dynamic>>*: | ||
You define the data and Dashboard generates widgets using a renderer. Dynamic dashboards support edit mode that allows the end user to move, resize, and remove widgets. The React and Web Components for this are `<Dashboard>` and `<vaadin-dashboard>`, respectively. | ||
+ | ||
In Flow, the `Dashboard` and `DashboardWidget` classes are used for both approaches. | ||
|
||
* <<#static-dashboards,Static>>: declaratively / imperatively defining the widgets. The React and Web Components for this are `<DashboardLayout>` and `<vaadin-dashboard-layout>` respectively. | ||
* <<#dynamic-dashboards,Dynamic>>: widgets generated from data using a renderer; supports edit mode that allows the end user to move, resize and remove widgets. The React and Web Components for this are `<Dashboard>` and `<vaadin-dashboard>`, respectively. | ||
*Widgets, Columns & Rows*:: | ||
Widgets are placed in columns and rows automatically, in the order supplied, based on the dashboard's width and the <<columns-and-rows,column configuration>>. As the dashboard's width changes, the number of columns is automatically adjusted based on their configured minimum and maximum width, and the widget positions are adjusted so. | ||
+ | ||
You can't place a widget in a specific column or row. | ||
|
||
In Flow, the same `Dashboard` class is used for both approaches. | ||
*Scrolling*:: | ||
Dashboard scrolls vertically if the contents overflow its defined height. Individual widgets don't scroll (see <<widget-content-sizing>>). | ||
|
||
|
||
== Configuration | ||
|
||
The following configuration options are available for the dashboard: | ||
The following configuration options are available for the Dashboard component. | ||
|
||
=== Columns and Rows | ||
[[columns-and-rows]] | ||
=== Columns & Rows | ||
|
||
Column width can vary between a minimum and maximum size. The default maximum width is `1fr`, which allows the columns to expand to fill any available space. If a fixed length value is provided, empty space is left at the end of rows once the columns reach their maximum width. | ||
Column width can vary between a minimum and maximum size. The default maximum width is `1fr`, which allows the columns to expand to fill any available space. If a fixed length value is provided, empty space is reserved at the end of rows once the columns reach their maximum width. | ||
|
||
By default there is no limit on the number of columns, but one can be provided if needed. | ||
|
||
The height of each dashboard row is determined by the tallest widget currently in that row (whose height in turn is determined by its contents). A minimum row height determines the height of empty rows, such as when a widget's row span is stretched into a previously unoccupied row. The minimum height can be configured. | ||
The height of each dashboard row is determined by the tallest widget in that row, whose height in turn is determined by its contents. A minimum row height determines the height of empty rows, such as when a widget's row span is stretched into an unoccupied row. The minimum height can be configured. | ||
|
||
[.example] | ||
-- | ||
|
@@ -152,7 +163,7 @@ endif::[] | |
-- | ||
|
||
=== Dense Layout | ||
This mode uses the dense packing algorithm in the CSS grid layout model, which attempts to fill in empty slots in the layout by placing smaller widgets in them, potentially affecting the order of the widgets. It should be used with caution in user-configurable dashboards, as the automatic reordering of widgets may be confusing during editing. | ||
This mode uses the dense packing algorithm in the CSS grid layout model. It attempts to fill in empty slots in the layout by placing smaller widgets in them. This can affect the order of the widgets. It should be used with caution in user-configurable dashboards, as the automatic reordering of widgets may be confusing during editing. | ||
|
||
[.example] | ||
-- | ||
|
@@ -195,9 +206,9 @@ include::{root}/frontend/demo/component/dashboard/dashboard-dense-layout.ts[rend | |
|
||
== Widgets | ||
|
||
Widgets consist of a content area and a header containing the widget's title and a slot for additional elements. | ||
Widgets consist of a content area and a header containing the widget's title and a slot for more elements. | ||
|
||
[.example] | ||
[.example.short] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -221,24 +232,25 @@ include::{root}/frontend/demo/component/dashboard/dashboard-widget-contents.ts[r | |
endif::[] | ||
-- | ||
|
||
The column span and row span can be set to make the widget take up more than one column or row in the dashboard's layout. The actual number of columns a widget spans is limited by the number of columns currently in the dashboard, however. | ||
You can set the column span and row span to make a widget take up more than one column or row in the dashboard's layout. The actual number of columns a widget spans is limited by the current number of columns in the dashboard, however. | ||
|
||
|
||
=== Widget Content Sizing | ||
|
||
The height of a widget's contents determine its default height, which can be expanded by row span and/or other widgets on the same dashboard row. The widget does not scroll, so the contents may need to incorporate a scrollable area of its own (e.g. by way of a <<../scroller#,Scroller>>) to accommodate a height smaller than its contents. | ||
The height of a widget's contents define its default height. The height can grow because of row span or other taller widgets on the same dashboard row. If the height of the widget is constrained (e.g., by an explicitly set height), the contents of the card can overflow. You may need to incorporate a scrollable area (e.g., with <<../scroller#,Scroller>>) to accommodate a height smaller than the contents you place in a widget. | ||
|
||
The widget's width, on the other hand, is determined by the current column width and the widget's column span. | ||
The width of a widget is determined by the current column width and the widget's column span. | ||
|
||
Contents that should cover the entire widget area should therefore be configured with 100% width and height, as well as a minimum height corresponding to its desired default height. | ||
|
||
|
||
[#static-dashboards] | ||
== Static Dashboards | ||
|
||
Static dashboards are populated declaratively (in React and Lit) / imperatively (in Flow), like normal layouts. They're a good choice for hard-coded dashboards. | ||
Static dashboards are populated declaratively (in React and Lit) / imperatively (in Flow), like normal layouts. They are a good choice for hard-coded dashboards. | ||
|
||
[cols="1,1m"] | ||
[.small] | ||
[cols="1s,2m",frame=none,grid=rows] | ||
|=== | ||
|
||
|Flow | ||
|
@@ -252,7 +264,7 @@ Static dashboards are populated declaratively (in React and Lit) / imperatively | |
|
||
|=== | ||
|
||
[.example] | ||
[.example.tall] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -280,9 +292,10 @@ endif::[] | |
[#dynamic-dashboards] | ||
== Dynamic, Editable Dashboards | ||
|
||
Dynamic dashboards provide end user editability out of the box. They're populated through a data binding API coupled with a widget renderer function, so that their contents can be easily persisted to and loaded from storage, such as a database. | ||
Dynamic dashboards offer end users the possibility to edit the layout. Dynamic dashboards are populated through a data-binding API coupled with a widget renderer function. This makes the layout configuration easy to persist and load from storage, such as a database. | ||
|
||
[cols="1,1m"] | ||
[.small] | ||
[cols="1s,2m",frame=none,grid=rows] | ||
|=== | ||
|
||
|Flow | ||
|
@@ -296,7 +309,7 @@ Dynamic dashboards provide end user editability out of the box. They're populate | |
|
||
|=== | ||
|
||
[.example] | ||
[.example.tall] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -347,15 +360,13 @@ endif::[] | |
|
||
=== Editing | ||
|
||
Dynamic dashboards can be made user editable by toggling on editing mode, as seen in the sample above. | ||
You can make dynamic dashboards editable by turning on editing mode, as seen in the sample above. | ||
|
||
.Editing mode should be temporary | ||
.Editing mode should be temporary. | ||
[NOTE] | ||
==== | ||
Editing mode is intended as a temporary state that is engaged when the end user wants to edit the dashboard's contents, and disengaged when they're done editing, at which point the widget configuration is typically persisted to storage. | ||
==== | ||
The end user turns on editing mode when they want to edit the dashboard's contents and turns it off when they finish editing. When turned off, you typically want to persist the dashboard configuration to a storage. | ||
|
||
The following operations are available in editing mode: | ||
The following operations are available in editing mode. | ||
|
||
==== Widget Selection by Keyboard | ||
|
||
|
@@ -365,35 +376,35 @@ Widget selection is not required for editing by pointer device. | |
|
||
==== Moving Widgets | ||
|
||
In editing mode, widgets can be moved around by | ||
In editing mode, widgets can be moved around by: | ||
|
||
* Drag & drop | ||
* Arrow keys, once the widget has been selected | ||
* An accessible move-mode engaged by clicking the drag-handle in the widget's top left corner. Move-mode is disengaged by clicking the apply-button in the widget's center, or by pressing kbd:[Esc]. | ||
* drag & drop; | ||
* arrow keys, once the widget has been selected; | ||
* an accessible move-mode engaged by clicking the drag-handle in the widget's top left corner. Move-mode is disengaged by clicking the apply-button in the widget's center, or by pressing kbd:[Esc]. | ||
|
||
(Currently widgets can only be moved backwards and forwards; moving a widget past the start or end of a row moves it to the preceding or following row.) | ||
Widgets can only be moved backwards and forwards. Moving a widget past the start or end of a row moves it to the preceding or following row. | ||
|
||
==== Resizing Widgets | ||
|
||
In editing mode, widgets can be resized by increasing and decreasing their column span and row span by | ||
In editing mode, widgets can be resized by increasing and decreasing their column span and row span by: | ||
|
||
* Dragging from the drag-handle in the widget's bottom right corner | ||
* kbd:[Shift] + arrow keys, once the widget has been selected | ||
* An accessible resize-mode engaged by clicking the resize-handle. Resize-mode is disengaged by clicking the apply-button in the widget's center, or by pressing kbd:[Esc]. | ||
* dragging from the drag-handle in the widget's bottom right corner; | ||
* kbd:[Shift] + arrow keys, once the widget has been selected; | ||
* an accessible resize-mode engaged by clicking the resize-handle. Resize-mode is disengaged by clicking the apply-button in the widget's center, or by pressing kbd:[Esc]. | ||
|
||
==== Removing Widgets | ||
|
||
In editing mode, widgets can be removed by clicking the remove-button in the widget's top right corner. | ||
In editing mode, widgets can be removed by clicking the [guilabel]*Remove* button in the widget's top right corner. | ||
|
||
==== Adding Widgets | ||
|
||
Dashboard has no built-in mechanism for adding new widgets, but this can easily be implemented using an external widget selector, such as a <<../select#,Select>> drop-down, that adds the corresponding item to the dashboard. | ||
Dashboard has no built-in mechanism for adding new widgets. You can implement this using an external widget selector, such as a <<../select#,Select>> drop-down, that adds the corresponding item to the dashboard. | ||
|
||
==== Screen Reader Announcements | ||
|
||
Although widget selection is announced via the widget's title, and the various buttons all have accessible names, the component does not provide announcements of changes to the widget's position and size out of the box. These can be provided by listening to related events emitted by the component and updating custom live regions with appropriate announcements. | ||
Although widget selection is announced via a widget's title, and the various buttons all have accessible names, the component doesn't announce changes to a widget's position and size out of the box. These can be provided by listening to related events emitted by the component and updating custom live regions with appropriate announcements. | ||
|
||
[.example] | ||
[.example.tall] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -430,7 +441,7 @@ endif::[] | |
|
||
Dynamic dashboards, with their user-editable capabilities, often require the ability to persist and load customized widget configurations to and from storage, such as a database. | ||
|
||
The most straightforward way to persist widget configurations is by defining a custom widget/item type. This type can include additional custom metadata relevant to the widget content, in addition to the built-in widget/item properties. | ||
The most straightforward way to persist widget configurations is by defining a custom widget/item type. This type can include custom metadata relevant to the widget content, in addition to the built-in widget/item properties. | ||
|
||
Once you've defined your custom type, you can establish a mapping between your data model and the widget configuration. This involves: | ||
|
||
|
@@ -439,14 +450,14 @@ Once you've defined your custom type, you can establish a mapping between your d | |
|
||
This approach allows for flexible persistence of dashboard configurations, enabling users to save and load their customized layouts across sessions. | ||
|
||
For a simple example of how to implement this persistence approach, refer to the <<#dynamic-dashboards>> section above. While the example doesn’t explicitly demonstrate data persistence, it illustrates the concept of defining a custom type for the dashboard widgets. The specific implementation details depend on your chosen storage mechanism and data model. | ||
For a simple example of how to implement this persistence approach, see the <<#dynamic-dashboards>> section above. While the example doesn't explicitly show how to persist the data, it illustrates the concept of defining a custom type for the dashboard widgets. The specific implementation details depend on your chosen storage mechanism and data model. | ||
|
||
|
||
== Dashboard Sections | ||
|
||
Complex dashboards can benefit from being divided into titled sections. Dashboard Sections always span the full width of the dashboard, and follow the same column and row configuration as the dashboard itself. They support the same moving and removal operations in editing mode as widgets. | ||
Complex dashboards can benefit from being divided into titled sections. Dashboard sections always span the full width of the dashboard, and follow the same column and row configuration as the dashboard itself. They support the same moving and removal operations in editing mode as widgets. | ||
|
||
[.example] | ||
[.example.tall] | ||
-- | ||
ifdef::flow[] | ||
[source,java] | ||
|
@@ -480,49 +491,49 @@ The following texts in the dashboard can be localized through the internationali | |
| Property | Description | ||
|
||
|selectWidget | ||
|Widget selection trigger | ||
|Widget selection trigger. | ||
|
||
|deselectWidget | ||
|Widget deselection trigger | ||
|Widget deselection trigger. | ||
|
||
|selectSection | ||
|Section selection trigger | ||
|Section selection trigger. | ||
|
||
|deselectSection | ||
|Section deselection trigger | ||
|Section deselection trigger. | ||
|
||
|move | ||
|Button that engages move-mode | ||
|Button that engages move-mode. | ||
|
||
|moveForward | ||
|Move forward button (in move-mode) | ||
|Move forward button in move-mode. | ||
|
||
|moveBackward | ||
|Move backward button (in move-mode) | ||
|Move backward button in move-mode. | ||
|
||
|moveApply | ||
|Button that disengages move-mode | ||
|Button that disengages move-mode. | ||
|
||
|resize | ||
|Button that engages resize-mode | ||
|Button that engages resize-mode. | ||
|
||
|resizeGrowWidth | ||
|Grow width button (in resize-mode) | ||
|Grow width button in resize-mode. | ||
|
||
|resizeShrinkWidth | ||
|Shrink width button (in resize-mode) | ||
|Shrink width button in resize-mode. | ||
|
||
|resizeGrowHeight | ||
|Grow height button (in resize-mode) | ||
|Grow height button in resize-mode. | ||
|
||
|resizeShrinkHeight | ||
|Shrink height button (in resize-mode) | ||
|Shrink height button in resize-mode. | ||
|
||
|resizeApply | ||
|Button that disengages resize-mode | ||
|Button that disengages resize-mode. | ||
|
||
|remove | ||
|Remove button | ||
|Remove button. | ||
|
||
|=== | ||
|
||
|
@@ -564,3 +575,16 @@ UNCOMMENT ONCE CARD PAGE EXISTS | |
//// | ||
|
||
[discussion-id]`d59db2ee-c3dd-446d-bd0d-40224b1f141e` | ||
|
||
++++ | ||
<style> | ||
/* Limit the amount of layout shifting when examples are rendered */ | ||
.code-example:not(.short) .render { | ||
min-height: 450px !important; | ||
} | ||
.code-example.tall .render { | ||
min-height: 700px !important; | ||
} | ||
</style> | ||
++++ |