@vaadin/dashboard 24.8.0-alpha7 → 24.8.0-alpha9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/dashboard",
3
- "version": "24.8.0-alpha7",
3
+ "version": "24.8.0-alpha9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,16 +37,16 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@open-wc/dedupe-mixin": "^1.3.0",
40
- "@vaadin/button": "24.8.0-alpha7",
41
- "@vaadin/component-base": "24.8.0-alpha7",
42
- "@vaadin/vaadin-lumo-styles": "24.8.0-alpha7",
43
- "@vaadin/vaadin-material-styles": "24.8.0-alpha7",
44
- "@vaadin/vaadin-themable-mixin": "24.8.0-alpha7",
40
+ "@vaadin/button": "24.8.0-alpha9",
41
+ "@vaadin/component-base": "24.8.0-alpha9",
42
+ "@vaadin/vaadin-lumo-styles": "24.8.0-alpha9",
43
+ "@vaadin/vaadin-material-styles": "24.8.0-alpha9",
44
+ "@vaadin/vaadin-themable-mixin": "24.8.0-alpha9",
45
45
  "lit": "^3.0.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@vaadin/chai-plugins": "24.8.0-alpha7",
49
- "@vaadin/test-runner-commands": "24.8.0-alpha7",
48
+ "@vaadin/chai-plugins": "24.8.0-alpha9",
49
+ "@vaadin/test-runner-commands": "24.8.0-alpha9",
50
50
  "@vaadin/testing-helpers": "^1.1.0"
51
51
  },
52
52
  "cvdlName": "vaadin-dashboard",
@@ -54,5 +54,5 @@
54
54
  "web-types.json",
55
55
  "web-types.lit.json"
56
56
  ],
57
- "gitHead": "7e65e14cbdcc372ab89620ba00e04251291d3c63"
57
+ "gitHead": "4de3809275ddfd733b0d13fd02af8faf73eb6770"
58
58
  }
@@ -101,3 +101,31 @@ export function fireResize(element, colspanDelta, rowspanDelta) {
101
101
  export function fireRemove(element) {
102
102
  element.dispatchEvent(new CustomEvent('item-remove', { bubbles: true }));
103
103
  }
104
+
105
+ /**
106
+ * Walks up the DOM tree starting from `node`, returning the first ancestor which is an instance of the given `baseClass`.
107
+ *
108
+ * @param {Node} node - starting node
109
+ * @param {Function} baseClass - constructor, e.g. `Dashboard`
110
+ * @returns {HTMLElement | null}
111
+ */
112
+ export function findAncestorInstance(node, baseClass) {
113
+ while (node) {
114
+ if (node instanceof baseClass) {
115
+ return node;
116
+ }
117
+ if (node instanceof ShadowRoot) {
118
+ node = node.host;
119
+ } else {
120
+ const rootNode = node.getRootNode();
121
+ if (rootNode instanceof ShadowRoot) {
122
+ node = rootNode.host;
123
+ } else if (node.parentNode) {
124
+ node = node.parentNode;
125
+ } else {
126
+ node = null;
127
+ }
128
+ }
129
+ }
130
+ return null;
131
+ }
@@ -102,7 +102,6 @@ class DashboardSection extends DashboardItemMixin(ElementMixin(ThemableMixin(Pol
102
102
  }
103
103
 
104
104
  ::slotted(*) {
105
- --_vaadin-dashboard-title-level: 3;
106
105
  --_vaadin-dashboard-item-column: span
107
106
  min(
108
107
  var(--vaadin-dashboard-item-colspan, 1),
@@ -166,6 +165,11 @@ class DashboardSection extends DashboardItemMixin(ElementMixin(ThemableMixin(Pol
166
165
  value: '',
167
166
  },
168
167
 
168
+ /* @private */
169
+ __rootHeadingLevel: {
170
+ type: Number,
171
+ },
172
+
169
173
  /** @private */
170
174
  __childCount: {
171
175
  type: Number,
@@ -184,7 +188,9 @@ class DashboardSection extends DashboardItemMixin(ElementMixin(ThemableMixin(Pol
184
188
 
185
189
  <header part="header">
186
190
  ${this.__renderDragHandle()}
187
- <h2 id="title" part="title">${this.sectionTitle}</h2>
191
+ <div id="title" role="heading" aria-level=${this.__rootHeadingLevel || 2} part="title"
192
+ >${this.sectionTitle}</div
193
+ >
188
194
  ${this.__renderRemoveButton()}
189
195
  </header>
190
196
  </div>
@@ -13,9 +13,10 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
13
13
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
14
14
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
15
15
  import { css, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
16
- import { SYNCHRONIZED_ATTRIBUTES, WRAPPER_LOCAL_NAME } from './vaadin-dashboard-helpers.js';
16
+ import { findAncestorInstance, SYNCHRONIZED_ATTRIBUTES, WRAPPER_LOCAL_NAME } from './vaadin-dashboard-helpers.js';
17
17
  import { DashboardItemMixin } from './vaadin-dashboard-item-mixin.js';
18
18
  import { getDefaultI18n } from './vaadin-dashboard-item-mixin.js';
19
+ import { DashboardSection } from './vaadin-dashboard-section.js';
19
20
 
20
21
  /**
21
22
  * A Widget component for use with the Dashboard component
@@ -193,11 +194,15 @@ class DashboardWidget extends DashboardItemMixin(ElementMixin(ThemableMixin(Poly
193
194
  widgetTitle: {
194
195
  type: String,
195
196
  value: '',
196
- observer: '__onWidgetTitleChanged',
197
197
  },
198
198
 
199
199
  /* @private */
200
- __nestedHeadingLevel: {
200
+ __rootHeadingLevel: {
201
+ type: Number,
202
+ },
203
+
204
+ /* @private */
205
+ __isNestedWidget: {
201
206
  type: Boolean,
202
207
  value: false,
203
208
  },
@@ -213,10 +218,7 @@ class DashboardWidget extends DashboardItemMixin(ElementMixin(ThemableMixin(Poly
213
218
  ${this.__renderFocusButton('selectWidget')}
214
219
 
215
220
  <header part="header">
216
- ${this.__renderDragHandle()}
217
- ${this.__nestedHeadingLevel
218
- ? html`<h3 id="title" part="title" .hidden=${!this.widgetTitle}>${this.widgetTitle}</h3>`
219
- : html`<h2 id="title" part="title" .hidden=${!this.widgetTitle}>${this.widgetTitle}</h2>`}
221
+ ${this.__renderDragHandle()} ${this.__renderWidgetTitle()}
220
222
  <slot name="header-content"></slot>
221
223
  ${this.__renderRemoveButton()}
222
224
  </header>
@@ -240,13 +242,15 @@ class DashboardWidget extends DashboardItemMixin(ElementMixin(ThemableMixin(Poly
240
242
  this.toggleAttribute(attr, !!wrapper[attr]);
241
243
  });
242
244
  this.__i18n = wrapper.i18n;
245
+ this.__rootHeadingLevel = wrapper.__rootHeadingLevel;
243
246
  }
244
247
 
248
+ this.__updateNestedState();
245
249
  const undefinedAncestor = this.closest('*:not(:defined)');
246
250
  if (undefinedAncestor) {
247
- customElements.whenDefined(undefinedAncestor.localName).then(() => queueMicrotask(() => this.__updateTitle()));
248
- } else {
249
- this.__updateTitle();
251
+ customElements.whenDefined(undefinedAncestor.localName).then(() => {
252
+ queueMicrotask(() => this.__updateNestedState());
253
+ });
250
254
  }
251
255
  }
252
256
 
@@ -259,14 +263,29 @@ class DashboardWidget extends DashboardItemMixin(ElementMixin(ThemableMixin(Poly
259
263
  }
260
264
 
261
265
  /** @private */
262
- __onWidgetTitleChanged() {
263
- this.__updateTitle();
266
+ __renderWidgetTitle() {
267
+ let effectiveHeadingLevel = this.__rootHeadingLevel;
268
+ // Default to 2 if not defined
269
+ if (effectiveHeadingLevel == null) {
270
+ effectiveHeadingLevel = 2;
271
+ }
272
+ // Increase level by 1 for widgets in sections
273
+ if (this.__isNestedWidget) {
274
+ effectiveHeadingLevel += 1;
275
+ }
276
+ return html`<div
277
+ id="title"
278
+ part="title"
279
+ role="heading"
280
+ aria-level=${effectiveHeadingLevel}
281
+ .hidden=${!this.widgetTitle}
282
+ >${this.widgetTitle}</div
283
+ >`;
264
284
  }
265
285
 
266
286
  /** @private */
267
- __updateTitle() {
268
- const titleLevel = getComputedStyle(this).getPropertyValue('--_vaadin-dashboard-title-level');
269
- this.__nestedHeadingLevel = titleLevel === '3';
287
+ __updateNestedState() {
288
+ this.__isNestedWidget = !!findAncestorInstance(this, DashboardSection);
270
289
  }
271
290
  }
272
291
 
@@ -202,11 +202,11 @@ export interface DashboardI18n {
202
202
  *
203
203
  * The following state attributes are available for styling:
204
204
  *
205
- * Attribute | Description
206
- * ---------------|-------------
207
- * `editable` | Set when the dashboard is editable.
208
- * `dense-layout` | Set when the dashboard is in dense mode.
209
- * `item-selected`| Set when an item is selected.
205
+ * Attribute | Description
206
+ * ---------------------|-------------
207
+ * `editable` | Set when the dashboard is editable.
208
+ * `dense-layout` | Set when the dashboard is in dense mode.
209
+ * `item-selected` | Set when an item is selected.
210
210
  *
211
211
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
212
212
  *
@@ -243,6 +243,16 @@ declare class Dashboard<TItem extends DashboardItem = DashboardItem> extends Das
243
243
  */
244
244
  editable: boolean;
245
245
 
246
+ /**
247
+ * Root heading level for sections and widgets. Defaults to 2.
248
+ *
249
+ * If changed to e.g. 1:
250
+ * - sections will have the attribute `aria-level` with value 1
251
+ * - non-nested widgets will have the attribute `aria-level` with value 1
252
+ * - nested widgets will have the attribute `aria-level` with value 2
253
+ */
254
+ rootHeadingLevel: number | null | undefined;
255
+
246
256
  /**
247
257
  * The object used to localize this component. To change the default
248
258
  * localization, replace this with an object that provides all properties, or
@@ -82,11 +82,11 @@ import { WidgetResizeController } from './widget-resize-controller.js';
82
82
  *
83
83
  * The following state attributes are available for styling:
84
84
  *
85
- * Attribute | Description
86
- * ---------------|-------------
87
- * `editable` | Set when the dashboard is editable.
88
- * `dense-layout` | Set when the dashboard is in dense mode.
89
- * `item-selected`| Set when an item is selected.
85
+ * Attribute | Description
86
+ * ---------------------|-------------
87
+ * `editable` | Set when the dashboard is editable.
88
+ * `dense-layout` | Set when the dashboard is in dense mode.
89
+ * `item-selected` | Set when an item is selected.
90
90
  *
91
91
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
92
92
  *
@@ -166,6 +166,20 @@ class Dashboard extends DashboardLayoutMixin(
166
166
  type: Boolean,
167
167
  },
168
168
 
169
+ /**
170
+ * Root heading level for sections and widgets. Defaults to 2.
171
+ *
172
+ * If changed to e.g. 1:
173
+ * - sections will have the attribute `aria-level` with value 1
174
+ * - non-nested widgets will have the attribute `aria-level` with value 1
175
+ * - nested widgets will have the attribute `aria-level` with value 2
176
+ */
177
+ rootHeadingLevel: {
178
+ type: Number,
179
+ value: 2,
180
+ sync: true,
181
+ },
182
+
169
183
  /** @private */
170
184
  __childCount: {
171
185
  type: Number,
@@ -175,7 +189,7 @@ class Dashboard extends DashboardLayoutMixin(
175
189
  }
176
190
 
177
191
  static get observers() {
178
- return ['__itemsOrRendererChanged(items, renderer, editable, __effectiveI18n)'];
192
+ return ['__itemsOrRendererChanged(items, renderer, editable, __effectiveI18n, rootHeadingLevel)'];
179
193
  }
180
194
 
181
195
  /**
@@ -261,6 +275,7 @@ class Dashboard extends DashboardLayoutMixin(
261
275
  wrapper.firstElementChild.toggleAttribute(attr, !!wrapper[attr]);
262
276
  });
263
277
  wrapper.firstElementChild.__i18n = this.__effectiveI18n;
278
+ wrapper.firstElementChild.__rootHeadingLevel = this.rootHeadingLevel;
264
279
  }
265
280
  });
266
281
  }
@@ -304,6 +319,7 @@ class Dashboard extends DashboardLayoutMixin(
304
319
 
305
320
  SYNCHRONIZED_ATTRIBUTES.forEach((attr) => section.toggleAttribute(attr, !!wrapper[attr]));
306
321
  section.__i18n = this.__effectiveI18n;
322
+ section.__rootHeadingLevel = this.rootHeadingLevel;
307
323
 
308
324
  // Render the subitems
309
325
  section.__childCount = item.items.length;
@@ -428,6 +444,7 @@ class Dashboard extends DashboardLayoutMixin(
428
444
  wrapper['first-child'] = item === getItemsArrayOfItem(item, this.items)[0];
429
445
  wrapper['last-child'] = item === getItemsArrayOfItem(item, this.items).slice(-1)[0];
430
446
  wrapper.i18n = this.__effectiveI18n;
447
+ wrapper.__rootHeadingLevel = this.rootHeadingLevel;
431
448
  }
432
449
 
433
450
  /** @private */
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/dashboard",
4
- "version": "24.8.0-alpha7",
4
+ "version": "24.8.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -136,7 +136,7 @@
136
136
  },
137
137
  {
138
138
  "name": "vaadin-dashboard",
139
- "description": "A responsive, grid-based dashboard layout component\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha7/#/elements/vaadin-dashboard#property-items) property.\nSet a renderer function to the [`renderer`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha7/#/elements/vaadin-dashboard#property-renderer) property.\n\nThe widgets and the sections will be generated and configured based on the renderer and the items provided.\n\n```html\n<vaadin-dashboard></vaadin-dashboard>\n```\n```js\nconst dashboard = document.querySelector('vaadin-dashboard');\n\ndashboard.items = [\n { title: 'Widget 1 title', content: 'Text 1', rowspan: 2 },\n { title: 'Widget 2 title', content: 'Text 2', colspan: 2 },\n {\n title: 'Section title',\n items: [{ title: 'Widget in section title', content: 'Text 3' }]\n },\n // ... more items\n];\n\ndashboard.renderer = (root, _dashboard, { item }) => {\n const widget = root.firstElementChild || document.createElement('vaadin-dashboard-widget');\n if (!root.contains(widget)) {\n root.appendChild(widget);\n }\n widget.widgetTitle = item.title;\n widget.textContent = item.content;\n};\n```\n\n### Styling\n\nThe following custom properties are available:\n\nCustom Property | Description\n------------------------------------|-------------\n`--vaadin-dashboard-col-min-width` | minimum column width of the dashboard\n`--vaadin-dashboard-col-max-width` | maximum column width of the dashboard\n`--vaadin-dashboard-row-min-height` | minimum row height of the dashboard\n`--vaadin-dashboard-col-max-count` | maximum column count of the dashboard\n`--vaadin-dashboard-gap` | gap between child elements. Must be in length units (0 is not allowed, 0px is)\n`--vaadin-dashboard-padding` | space around the dashboard's outer edges. Must be in length units (0 is not allowed, 0px is)\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------|-------------\n`editable` | Set when the dashboard is editable.\n`dense-layout` | Set when the dashboard is in dense mode.\n`item-selected`| Set when an item is selected.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
139
+ "description": "A responsive, grid-based dashboard layout component\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha9/#/elements/vaadin-dashboard#property-items) property.\nSet a renderer function to the [`renderer`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha9/#/elements/vaadin-dashboard#property-renderer) property.\n\nThe widgets and the sections will be generated and configured based on the renderer and the items provided.\n\n```html\n<vaadin-dashboard></vaadin-dashboard>\n```\n```js\nconst dashboard = document.querySelector('vaadin-dashboard');\n\ndashboard.items = [\n { title: 'Widget 1 title', content: 'Text 1', rowspan: 2 },\n { title: 'Widget 2 title', content: 'Text 2', colspan: 2 },\n {\n title: 'Section title',\n items: [{ title: 'Widget in section title', content: 'Text 3' }]\n },\n // ... more items\n];\n\ndashboard.renderer = (root, _dashboard, { item }) => {\n const widget = root.firstElementChild || document.createElement('vaadin-dashboard-widget');\n if (!root.contains(widget)) {\n root.appendChild(widget);\n }\n widget.widgetTitle = item.title;\n widget.textContent = item.content;\n};\n```\n\n### Styling\n\nThe following custom properties are available:\n\nCustom Property | Description\n------------------------------------|-------------\n`--vaadin-dashboard-col-min-width` | minimum column width of the dashboard\n`--vaadin-dashboard-col-max-width` | maximum column width of the dashboard\n`--vaadin-dashboard-row-min-height` | minimum row height of the dashboard\n`--vaadin-dashboard-col-max-count` | maximum column count of the dashboard\n`--vaadin-dashboard-gap` | gap between child elements. Must be in length units (0 is not allowed, 0px is)\n`--vaadin-dashboard-padding` | space around the dashboard's outer edges. Must be in length units (0 is not allowed, 0px is)\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|-------------\n`editable` | Set when the dashboard is editable.\n`dense-layout` | Set when the dashboard is in dense mode.\n`item-selected` | Set when an item is selected.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
140
140
  "attributes": [
141
141
  {
142
142
  "name": "dense-layout",
@@ -167,6 +167,17 @@
167
167
  ]
168
168
  }
169
169
  },
170
+ {
171
+ "name": "root-heading-level",
172
+ "description": "Root heading level for sections and widgets. Defaults to 2.\n\nIf changed to e.g. 1:\n- sections will have the attribute `aria-level` with value 1\n- non-nested widgets will have the attribute `aria-level` with value 1\n- nested widgets will have the attribute `aria-level` with value 2",
173
+ "value": {
174
+ "type": [
175
+ "number",
176
+ "null",
177
+ "undefined"
178
+ ]
179
+ }
180
+ },
170
181
  {
171
182
  "name": "theme",
172
183
  "description": "The theme variants to apply to the component.",
@@ -231,6 +242,17 @@
231
242
  "undefined"
232
243
  ]
233
244
  }
245
+ },
246
+ {
247
+ "name": "rootHeadingLevel",
248
+ "description": "Root heading level for sections and widgets. Defaults to 2.\n\nIf changed to e.g. 1:\n- sections will have the attribute `aria-level` with value 1\n- non-nested widgets will have the attribute `aria-level` with value 1\n- nested widgets will have the attribute `aria-level` with value 2",
249
+ "value": {
250
+ "type": [
251
+ "number",
252
+ "null",
253
+ "undefined"
254
+ ]
255
+ }
234
256
  }
235
257
  ],
236
258
  "events": [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/dashboard",
4
- "version": "24.8.0-alpha7",
4
+ "version": "24.8.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  {
60
60
  "name": "vaadin-dashboard",
61
- "description": "A responsive, grid-based dashboard layout component\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha7/#/elements/vaadin-dashboard#property-items) property.\nSet a renderer function to the [`renderer`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha7/#/elements/vaadin-dashboard#property-renderer) property.\n\nThe widgets and the sections will be generated and configured based on the renderer and the items provided.\n\n```html\n<vaadin-dashboard></vaadin-dashboard>\n```\n```js\nconst dashboard = document.querySelector('vaadin-dashboard');\n\ndashboard.items = [\n { title: 'Widget 1 title', content: 'Text 1', rowspan: 2 },\n { title: 'Widget 2 title', content: 'Text 2', colspan: 2 },\n {\n title: 'Section title',\n items: [{ title: 'Widget in section title', content: 'Text 3' }]\n },\n // ... more items\n];\n\ndashboard.renderer = (root, _dashboard, { item }) => {\n const widget = root.firstElementChild || document.createElement('vaadin-dashboard-widget');\n if (!root.contains(widget)) {\n root.appendChild(widget);\n }\n widget.widgetTitle = item.title;\n widget.textContent = item.content;\n};\n```\n\n### Styling\n\nThe following custom properties are available:\n\nCustom Property | Description\n------------------------------------|-------------\n`--vaadin-dashboard-col-min-width` | minimum column width of the dashboard\n`--vaadin-dashboard-col-max-width` | maximum column width of the dashboard\n`--vaadin-dashboard-row-min-height` | minimum row height of the dashboard\n`--vaadin-dashboard-col-max-count` | maximum column count of the dashboard\n`--vaadin-dashboard-gap` | gap between child elements. Must be in length units (0 is not allowed, 0px is)\n`--vaadin-dashboard-padding` | space around the dashboard's outer edges. Must be in length units (0 is not allowed, 0px is)\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------|-------------\n`editable` | Set when the dashboard is editable.\n`dense-layout` | Set when the dashboard is in dense mode.\n`item-selected`| Set when an item is selected.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
61
+ "description": "A responsive, grid-based dashboard layout component\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha9/#/elements/vaadin-dashboard#property-items) property.\nSet a renderer function to the [`renderer`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-alpha9/#/elements/vaadin-dashboard#property-renderer) property.\n\nThe widgets and the sections will be generated and configured based on the renderer and the items provided.\n\n```html\n<vaadin-dashboard></vaadin-dashboard>\n```\n```js\nconst dashboard = document.querySelector('vaadin-dashboard');\n\ndashboard.items = [\n { title: 'Widget 1 title', content: 'Text 1', rowspan: 2 },\n { title: 'Widget 2 title', content: 'Text 2', colspan: 2 },\n {\n title: 'Section title',\n items: [{ title: 'Widget in section title', content: 'Text 3' }]\n },\n // ... more items\n];\n\ndashboard.renderer = (root, _dashboard, { item }) => {\n const widget = root.firstElementChild || document.createElement('vaadin-dashboard-widget');\n if (!root.contains(widget)) {\n root.appendChild(widget);\n }\n widget.widgetTitle = item.title;\n widget.textContent = item.content;\n};\n```\n\n### Styling\n\nThe following custom properties are available:\n\nCustom Property | Description\n------------------------------------|-------------\n`--vaadin-dashboard-col-min-width` | minimum column width of the dashboard\n`--vaadin-dashboard-col-max-width` | maximum column width of the dashboard\n`--vaadin-dashboard-row-min-height` | minimum row height of the dashboard\n`--vaadin-dashboard-col-max-count` | maximum column count of the dashboard\n`--vaadin-dashboard-gap` | gap between child elements. Must be in length units (0 is not allowed, 0px is)\n`--vaadin-dashboard-padding` | space around the dashboard's outer edges. Must be in length units (0 is not allowed, 0px is)\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|-------------\n`editable` | Set when the dashboard is editable.\n`dense-layout` | Set when the dashboard is in dense mode.\n`item-selected` | Set when an item is selected.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
62
62
  "extension": true,
63
63
  "attributes": [
64
64
  {
@@ -96,6 +96,13 @@
96
96
  "kind": "expression"
97
97
  }
98
98
  },
99
+ {
100
+ "name": ".rootHeadingLevel",
101
+ "description": "Root heading level for sections and widgets. Defaults to 2.\n\nIf changed to e.g. 1:\n- sections will have the attribute `aria-level` with value 1\n- non-nested widgets will have the attribute `aria-level` with value 1\n- nested widgets will have the attribute `aria-level` with value 2",
102
+ "value": {
103
+ "kind": "expression"
104
+ }
105
+ },
99
106
  {
100
107
  "name": "@dashboard-item-move-mode-changed",
101
108
  "description": "Fired when an item move mode changed",