@vaadin/side-nav 24.2.0-alpha1 → 24.2.0-alpha10

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/README.md CHANGED
@@ -49,9 +49,14 @@ import '@vaadin/side-nav';
49
49
  ## Themes
50
50
 
51
51
  Vaadin components come with two built-in [themes](https://vaadin.com/docs/latest/styling), Lumo and Material.
52
- This component currently does not support Material theme.
53
52
  The [main entrypoint](https://github.com/vaadin/web-components/blob/main/packages/side-nav/vaadin-side-nav.js) of the package uses the Lumo theme.
54
53
 
54
+ To use the Material theme, import the component from the `theme/material` folder:
55
+
56
+ ```js
57
+ import '@vaadin/side-nav/theme/material/vaadin-side-nav.js';
58
+ ```
59
+
55
60
  You can also import the Lumo version of the component explicitly:
56
61
 
57
62
  ```js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/side-nav",
3
- "version": "24.2.0-alpha1",
3
+ "version": "24.2.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,15 +35,15 @@
35
35
  "web-component"
36
36
  ],
37
37
  "dependencies": {
38
- "@vaadin/component-base": "24.2.0-alpha1",
39
- "@vaadin/vaadin-lumo-styles": "24.2.0-alpha1",
40
- "@vaadin/vaadin-material-styles": "24.2.0-alpha1",
41
- "@vaadin/vaadin-themable-mixin": "24.2.0-alpha1",
38
+ "@vaadin/component-base": "24.2.0-alpha10",
39
+ "@vaadin/vaadin-lumo-styles": "24.2.0-alpha10",
40
+ "@vaadin/vaadin-material-styles": "24.2.0-alpha10",
41
+ "@vaadin/vaadin-themable-mixin": "24.2.0-alpha10",
42
42
  "lit": "^2.0.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@esm-bundle/chai": "^4.3.4",
46
- "@vaadin/testing-helpers": "^0.4.2",
46
+ "@vaadin/testing-helpers": "^0.5.0",
47
47
  "lit": "^2.0.0",
48
48
  "sinon": "^13.0.2"
49
49
  },
@@ -51,5 +51,5 @@
51
51
  "web-types.json",
52
52
  "web-types.lit.json"
53
53
  ],
54
- "gitHead": "0dbb118320203ab6c0c07450a3e718815367589f"
54
+ "gitHead": "ca16b5f88b00ae05fb6d7c7e9874525048e389f0"
55
55
  }
@@ -10,10 +10,20 @@ export const sideNavItemBaseStyles = css`
10
10
  display: block;
11
11
  }
12
12
 
13
+ :host([hidden]),
13
14
  [hidden] {
14
15
  display: none !important;
15
16
  }
16
17
 
18
+ :host([disabled]) {
19
+ pointer-events: none;
20
+ }
21
+
22
+ [part='content'] {
23
+ display: flex;
24
+ align-items: center;
25
+ }
26
+
17
27
  [part='link'] {
18
28
  flex: auto;
19
29
  min-width: 0;
@@ -28,6 +38,11 @@ export const sideNavItemBaseStyles = css`
28
38
  -webkit-appearance: none;
29
39
  appearance: none;
30
40
  flex: none;
41
+ position: relative;
42
+ margin: 0;
43
+ padding: 0;
44
+ border: 0;
45
+ background: transparent;
31
46
  }
32
47
 
33
48
  [part='children'] {
@@ -40,19 +55,6 @@ export const sideNavItemBaseStyles = css`
40
55
  display: none !important;
41
56
  }
42
57
 
43
- :host(:not([path])) a {
44
- position: relative;
45
- }
46
-
47
- :host(:not([path])) button::after {
48
- content: '';
49
- position: absolute;
50
- top: 0;
51
- right: 0;
52
- bottom: 0;
53
- left: 0;
54
- }
55
-
56
58
  slot[name='prefix'],
57
59
  slot[name='suffix'] {
58
60
  flex: none;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+
8
+ export interface SideNavI18n {
9
+ toggle: string;
10
+ }
11
+
12
+ export declare function SideNavChildrenMixin<T extends Constructor<HTMLElement>>(
13
+ base: T,
14
+ ): Constructor<SideNavChildrenMixinClass> & T;
15
+
16
+ export declare class SideNavChildrenMixinClass {
17
+ /**
18
+ * The object used to localize this component.
19
+ *
20
+ * To change the default localization, replace the entire
21
+ * `i18n` object with a custom one.
22
+ *
23
+ * The object has the following structure and default values:
24
+ * ```
25
+ * {
26
+ * toggle: 'Toggle child items'
27
+ * }
28
+ * ```
29
+ */
30
+ i18n: SideNavI18n;
31
+
32
+ /**
33
+ * List of child items of this component.
34
+ */
35
+ protected readonly _items: HTMLElement[];
36
+
37
+ /**
38
+ * Name of the slot to be used for children.
39
+ */
40
+ protected readonly _itemsSlotName: string;
41
+
42
+ /**
43
+ * Count of child items.
44
+ */
45
+ protected _itemsCount: number;
46
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
+
8
+ /**
9
+ * A controller that manages the item content children slot.
10
+ */
11
+ class ChildrenController extends SlotController {
12
+ constructor(host, slotName) {
13
+ super(host, slotName, null, { observe: true, multiple: true });
14
+ }
15
+
16
+ /**
17
+ * @protected
18
+ * @override
19
+ */
20
+ initAddedNode() {
21
+ this.host.requestUpdate();
22
+ }
23
+
24
+ /**
25
+ * @protected
26
+ * @override
27
+ */
28
+ teardownNode() {
29
+ this.host.requestUpdate();
30
+ }
31
+ }
32
+
33
+ /**
34
+ * @polymerMixin
35
+ */
36
+ export const SideNavChildrenMixin = (superClass) =>
37
+ class SideNavChildrenMixin extends superClass {
38
+ static get properties() {
39
+ return {
40
+ /**
41
+ * The object used to localize this component.
42
+ *
43
+ * To change the default localization, replace the entire
44
+ * `i18n` object with a custom one.
45
+ *
46
+ * The object has the following structure and default values:
47
+ * ```
48
+ * {
49
+ * toggle: 'Toggle child items'
50
+ * }
51
+ * ```
52
+ *
53
+ * @type {SideNavI18n}
54
+ * @default {English/US}
55
+ */
56
+ i18n: {
57
+ type: Object,
58
+ value: () => {
59
+ return {
60
+ toggle: 'Toggle child items',
61
+ };
62
+ },
63
+ },
64
+
65
+ /**
66
+ * Count of child items.
67
+ * @protected
68
+ */
69
+ _itemsCount: {
70
+ type: Number,
71
+ value: 0,
72
+ },
73
+ };
74
+ }
75
+
76
+ constructor() {
77
+ super();
78
+
79
+ this._childrenController = new ChildrenController(this, this._itemsSlotName);
80
+ }
81
+
82
+ /**
83
+ * List of child items of this component.
84
+ * @protected
85
+ */
86
+ get _items() {
87
+ return this._childrenController.nodes;
88
+ }
89
+
90
+ /**
91
+ * Name of the slot to be used for children.
92
+ * @protected
93
+ */
94
+ get _itemsSlotName() {
95
+ return 'children';
96
+ }
97
+
98
+ /** @protected */
99
+ firstUpdated() {
100
+ super.firstUpdated();
101
+
102
+ // Controller that detects changes to the side-nav items.
103
+ this.addController(this._childrenController);
104
+ }
105
+
106
+ /**
107
+ * @protected
108
+ * @override
109
+ */
110
+ willUpdate(props) {
111
+ super.willUpdate(props);
112
+
113
+ this._itemsCount = this._items.length;
114
+ }
115
+
116
+ /**
117
+ * @protected
118
+ * @override
119
+ */
120
+ updated(props) {
121
+ super.updated(props);
122
+
123
+ if (props.has('_itemsCount')) {
124
+ this.toggleAttribute('has-children', this._itemsCount > 0);
125
+ }
126
+
127
+ // Propagate i18n object to all the child items
128
+ if (props.has('_itemsCount') || props.has('i18n')) {
129
+ this._items.forEach((item) => {
130
+ item.i18n = this.i18n;
131
+ });
132
+ }
133
+ }
134
+ };
@@ -4,9 +4,11 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { LitElement } from 'lit';
7
+ import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
7
8
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
8
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
9
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+ import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
10
12
 
11
13
  /**
12
14
  * Fired when the `expanded` property changes.
@@ -56,6 +58,8 @@ export type SideNavItemEventMap = HTMLElementEventMap & SideNavItemCustomEventMa
56
58
  *
57
59
  * ### Styling
58
60
  *
61
+ * The following shadow DOM parts are available for styling:
62
+ *
59
63
  * Part name | Description
60
64
  * ----------------|----------------
61
65
  * `content` | The element that wraps link and toggle button
@@ -63,22 +67,30 @@ export type SideNavItemEventMap = HTMLElementEventMap & SideNavItemCustomEventMa
63
67
  * `link` | The clickable anchor used for navigation
64
68
  * `toggle-button` | The toggle button
65
69
  *
70
+ * The following state attributes are available for styling:
71
+ *
72
+ * Attribute | Description
73
+ * ---------------|-------------
74
+ * `disabled` | Set when the element is disabled.
75
+ * `expanded` | Set when the element is expanded.
76
+ * `has-children` | Set when the element has child items.
77
+ *
66
78
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
67
79
  *
68
80
  * @fires {CustomEvent} expanded-changed - Fired when the `expanded` property changes.
69
81
  */
70
- declare class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
82
+ declare class SideNavItem extends SideNavChildrenMixin(
83
+ DisabledMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))),
84
+ ) {
71
85
  /**
72
86
  * The path to navigate to
73
87
  */
74
88
  path: string | null | undefined;
75
89
 
76
90
  /**
77
- * A comma-separated list of alternative paths matching this item.
78
- *
79
- * @attr {string} path-aliases
91
+ * The list of alternative paths matching this item
80
92
  */
81
- pathAliases: string | null | undefined;
93
+ pathAliases: string[];
82
94
 
83
95
  /**
84
96
  * Whether to show the child items or not
@@ -90,7 +102,7 @@ declare class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitEle
90
102
  * Set when the item is appended to DOM or when navigated back
91
103
  * to the page that contains this item using the browser.
92
104
  */
93
- readonly active: boolean;
105
+ readonly current: boolean;
94
106
 
95
107
  addEventListener<K extends keyof SideNavItemEventMap>(
96
108
  type: K,
@@ -5,42 +5,19 @@
5
5
  */
6
6
  import { html, LitElement } from 'lit';
7
7
  import { ifDefined } from 'lit/directives/if-defined.js';
8
+ import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
9
+ import { screenReaderOnly } from '@vaadin/a11y-base/src/styles/sr-only-styles.js';
8
10
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
9
11
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
- import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
11
12
  import { matchPaths } from '@vaadin/component-base/src/url-utils.js';
12
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
14
  import { sideNavItemBaseStyles } from './vaadin-side-nav-base-styles.js';
15
+ import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
14
16
 
15
17
  function isEnabled() {
16
18
  return window.Vaadin && window.Vaadin.featureFlags && !!window.Vaadin.featureFlags.sideNavComponent;
17
19
  }
18
20
 
19
- /**
20
- * A controller to manage the item content children slot.
21
- */
22
- class ChildrenController extends SlotController {
23
- constructor(host) {
24
- super(host, 'children', null, { observe: true, multiple: true });
25
- }
26
-
27
- /**
28
- * @protected
29
- * @override
30
- */
31
- initAddedNode() {
32
- this.host.requestUpdate();
33
- }
34
-
35
- /**
36
- * @protected
37
- * @override
38
- */
39
- teardownNode() {
40
- this.host.requestUpdate();
41
- }
42
- }
43
-
44
21
  /**
45
22
  * A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.
46
23
  * Not intended to be used separately.
@@ -78,6 +55,8 @@ class ChildrenController extends SlotController {
78
55
  *
79
56
  * ### Styling
80
57
  *
58
+ * The following shadow DOM parts are available for styling:
59
+ *
81
60
  * Part name | Description
82
61
  * ----------------|----------------
83
62
  * `content` | The element that wraps link and toggle button
@@ -85,6 +64,14 @@ class ChildrenController extends SlotController {
85
64
  * `link` | The clickable anchor used for navigation
86
65
  * `toggle-button` | The toggle button
87
66
  *
67
+ * The following state attributes are available for styling:
68
+ *
69
+ * Attribute | Description
70
+ * ---------------|-------------
71
+ * `disabled` | Set when the element is disabled.
72
+ * `expanded` | Set when the element is expanded.
73
+ * `has-children` | Set when the element has child items.
74
+ *
88
75
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
89
76
  *
90
77
  * @fires {CustomEvent} expanded-changed - Fired when the `expanded` property changes.
@@ -92,9 +79,11 @@ class ChildrenController extends SlotController {
92
79
  * @extends LitElement
93
80
  * @mixes PolylitMixin
94
81
  * @mixes ThemableMixin
82
+ * @mixes DisabledMixin
95
83
  * @mixes ElementMixin
84
+ * @mixes SideNavChildrenMixin
96
85
  */
97
- class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
86
+ class SideNavItem extends SideNavChildrenMixin(DisabledMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
98
87
  static get is() {
99
88
  return 'vaadin-side-nav-item';
100
89
  }
@@ -107,11 +96,14 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
107
96
  path: String,
108
97
 
109
98
  /**
110
- * A comma-separated list of alternative paths matching this item.
99
+ * The list of alternative paths matching this item
111
100
  *
112
- * @attr {string} path-aliases
101
+ * @type {!Array<string>}
113
102
  */
114
- pathAliases: String,
103
+ pathAliases: {
104
+ type: Array,
105
+ value: () => [],
106
+ },
115
107
 
116
108
  /**
117
109
  * Whether to show the child items or not
@@ -132,7 +124,7 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
132
124
  *
133
125
  * @type {boolean}
134
126
  */
135
- active: {
127
+ current: {
136
128
  type: Boolean,
137
129
  value: false,
138
130
  readOnly: true,
@@ -142,13 +134,13 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
142
134
  }
143
135
 
144
136
  static get styles() {
145
- return sideNavItemBaseStyles;
137
+ return [screenReaderOnly, sideNavItemBaseStyles];
146
138
  }
147
139
 
148
140
  constructor() {
149
141
  super();
150
142
 
151
- this._childrenController = new ChildrenController(this);
143
+ this.__boundUpdateCurrent = this.__updateCurrent.bind(this);
152
144
  }
153
145
 
154
146
  /** @protected */
@@ -161,8 +153,7 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
161
153
  * @override
162
154
  */
163
155
  firstUpdated() {
164
- // Controller to detect whether the item has child items.
165
- this.addController(this._childrenController);
156
+ super.firstUpdated();
166
157
 
167
158
  // By default, if the user hasn't provided a custom role,
168
159
  // the role attribute is set to "listitem".
@@ -179,46 +170,60 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
179
170
  super.updated(props);
180
171
 
181
172
  if (props.has('path') || props.has('pathAliases')) {
182
- this.__updateActive();
173
+ this.__updateCurrent();
183
174
  }
184
175
 
185
- this.toggleAttribute('has-children', this._childrenController.nodes.length > 0);
176
+ // Ensure all the child items are disabled
177
+ if (props.has('disabled') || props.has('_itemsCount')) {
178
+ this._items.forEach((item) => {
179
+ item.disabled = this.disabled;
180
+ });
181
+ }
186
182
  }
187
183
 
188
184
  /** @protected */
189
185
  connectedCallback() {
190
186
  super.connectedCallback();
191
- this.__updateActive();
192
- this.__boundUpdateActive = this.__updateActive.bind(this);
193
- window.addEventListener('popstate', this.__boundUpdateActive);
187
+ this.__updateCurrent();
188
+
189
+ window.addEventListener('popstate', this.__boundUpdateCurrent);
194
190
  }
195
191
 
196
192
  /** @protected */
197
193
  disconnectedCallback() {
198
194
  super.disconnectedCallback();
199
- window.removeEventListener('popstate', this.__boundUpdateActive);
195
+ window.removeEventListener('popstate', this.__boundUpdateCurrent);
200
196
  }
201
197
 
202
198
  /** @protected */
203
199
  render() {
204
200
  return html`
205
201
  <div part="content" @click="${this._onContentClick}">
206
- <a href="${ifDefined(this.path)}" part="link" aria-current="${this.active ? 'page' : 'false'}">
202
+ <a
203
+ id="link"
204
+ ?disabled="${this.disabled}"
205
+ tabindex="${this.disabled || !this.path ? '-1' : '0'}"
206
+ href="${ifDefined(this.disabled ? null : this.path)}"
207
+ part="link"
208
+ aria-current="${this.current ? 'page' : 'false'}"
209
+ >
207
210
  <slot name="prefix"></slot>
208
211
  <slot></slot>
209
212
  <slot name="suffix"></slot>
210
213
  </a>
211
214
  <button
212
215
  part="toggle-button"
216
+ ?disabled="${this.disabled}"
213
217
  @click="${this._onButtonClick}"
214
218
  aria-controls="children"
215
219
  aria-expanded="${this.expanded}"
216
- aria-label="Toggle child items"
220
+ aria-labelledby="link i18n"
217
221
  ></button>
218
222
  </div>
219
- <ul part="children" ?hidden="${!this.expanded}">
223
+ <ul part="children" role="list" ?hidden="${!this.expanded}" aria-hidden="${this.expanded ? 'false' : 'true'}">
220
224
  <slot name="children"></slot>
221
225
  </ul>
226
+ <div class="sr-only" id="i18n">${this.i18n.toggle}</div>
222
227
  `;
223
228
  }
224
229
 
@@ -244,29 +249,21 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
244
249
  }
245
250
 
246
251
  /** @private */
247
- __updateActive() {
248
- if (!this.path && this.path !== '') {
249
- this._setActive(false);
250
- return;
251
- }
252
- this._setActive(this.__calculateActive());
253
- this.toggleAttribute('child-active', document.location.pathname.startsWith(this.path));
254
- if (this.active) {
255
- this.expanded = true;
252
+ __updateCurrent() {
253
+ this._setCurrent(this.__isCurrent());
254
+ if (this.current) {
255
+ this.expanded = this._items.length > 0;
256
256
  }
257
257
  }
258
258
 
259
259
  /** @private */
260
- __calculateActive() {
260
+ __isCurrent() {
261
261
  if (this.path == null) {
262
262
  return false;
263
263
  }
264
- if (matchPaths(document.location.pathname, this.path)) {
265
- return true;
266
- }
267
264
  return (
268
- this.pathAliases != null &&
269
- this.pathAliases.split(',').some((alias) => matchPaths(document.location.pathname, alias))
265
+ matchPaths(document.location.pathname, this.path) ||
266
+ this.pathAliases.some((alias) => matchPaths(document.location.pathname, alias))
270
267
  );
271
268
  }
272
269
  }
@@ -8,6 +8,9 @@ import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
8
8
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
9
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+ import { SideNavChildrenMixin, type SideNavI18n } from './vaadin-side-nav-children-mixin.js';
12
+
13
+ export type { SideNavI18n };
11
14
 
12
15
  /**
13
16
  * Fired when the `collapsed` property changes.
@@ -51,17 +54,27 @@ export type SideNavEventMap = HTMLElementEventMap & SideNavCustomEventMap;
51
54
  *
52
55
  * ### Styling
53
56
  *
57
+ * The following shadow DOM parts are available for styling:
58
+ *
54
59
  * Part name | Description
55
60
  * ----------------|----------------
56
61
  * `label` | The label element
57
62
  * `children` | The element that wraps child items
58
63
  * `toggle-button` | The toggle button
59
64
  *
65
+ * The following state attributes are available for styling:
66
+ *
67
+ * Attribute | Description
68
+ * -------------|-------------
69
+ * `collapsed` | Set when the element is collapsed.
70
+ * `focus-ring` | Set when the label is focused using the keyboard.
71
+ * `focused` | Set when the label is focused.
72
+ *
60
73
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
61
74
  *
62
75
  * @fires {CustomEvent} collapsed-changed - Fired when the `collapsed` property changes.
63
76
  */
64
- declare class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
77
+ declare class SideNav extends SideNavChildrenMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
65
78
  /**
66
79
  * Whether the side nav is collapsible. When enabled, the toggle icon is shown.
67
80
  */
@@ -11,6 +11,7 @@ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
11
  import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
12
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
13
  import { sideNavBaseStyles } from './vaadin-side-nav-base-styles.js';
14
+ import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
14
15
 
15
16
  function isEnabled() {
16
17
  return window.Vaadin && window.Vaadin.featureFlags && !!window.Vaadin.featureFlags.sideNavComponent;
@@ -47,12 +48,22 @@ function isEnabled() {
47
48
  *
48
49
  * ### Styling
49
50
  *
51
+ * The following shadow DOM parts are available for styling:
52
+ *
50
53
  * Part name | Description
51
54
  * ----------------|----------------
52
55
  * `label` | The label element
53
56
  * `children` | The element that wraps child items
54
57
  * `toggle-button` | The toggle button
55
58
  *
59
+ * The following state attributes are available for styling:
60
+ *
61
+ * Attribute | Description
62
+ * -------------|-------------
63
+ * `collapsed` | Set when the element is collapsed.
64
+ * `focus-ring` | Set when the label is focused using the keyboard.
65
+ * `focused` | Set when the label is focused.
66
+ *
56
67
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
57
68
  *
58
69
  * @fires {CustomEvent} collapsed-changed - Fired when the `collapsed` property changes.
@@ -61,8 +72,9 @@ function isEnabled() {
61
72
  * @mixes PolylitMixin
62
73
  * @mixes ThemableMixin
63
74
  * @mixes ElementMixin
75
+ * @mixes SideNavChildrenMixin
64
76
  */
65
- class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
77
+ class SideNav extends SideNavChildrenMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
66
78
  static get is() {
67
79
  return 'vaadin-side-nav';
68
80
  }
@@ -108,6 +120,15 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
108
120
  this._labelId = `side-nav-label-${generateUniqueId()}`;
109
121
  }
110
122
 
123
+ /**
124
+ * Name of the slot to be used for children.
125
+ * @protected
126
+ * @override
127
+ */
128
+ get _itemsSlotName() {
129
+ return '';
130
+ }
131
+
111
132
  /** @protected */
112
133
  get focusElement() {
113
134
  return this.shadowRoot.querySelector('button');
@@ -115,6 +136,8 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
115
136
 
116
137
  /** @protected */
117
138
  firstUpdated() {
139
+ super.firstUpdated();
140
+
118
141
  // By default, if the user hasn't provided a custom role,
119
142
  // the role attribute is set to "navigation".
120
143
  if (!this.hasAttribute('role')) {
@@ -129,12 +152,19 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
129
152
  part="label"
130
153
  @click="${this._onLabelClick}"
131
154
  aria-expanded="${ifDefined(this.collapsible ? !this.collapsed : null)}"
155
+ aria-hidden="${ifDefined(this.collapsible === false ? true : null)}"
132
156
  aria-controls="children"
133
157
  >
134
158
  <slot name="label" @slotchange="${this._onLabelSlotChange}"></slot>
135
159
  <span part="toggle-button" aria-hidden="true"></span>
136
160
  </button>
137
- <ul id="children" part="children" ?hidden="${this.collapsed}" aria-hidden="${this.collapsed ? 'true' : 'false'}">
161
+ <ul
162
+ id="children"
163
+ role="list"
164
+ part="children"
165
+ ?hidden="${this.collapsed}"
166
+ aria-hidden="${this.collapsed ? 'true' : 'false'}"
167
+ >
138
168
  <slot></slot>
139
169
  </ul>
140
170
  `;
@@ -4,14 +4,10 @@ import '@vaadin/vaadin-lumo-styles/sizing.js';
4
4
  import '@vaadin/vaadin-lumo-styles/spacing.js';
5
5
  import '@vaadin/vaadin-lumo-styles/style.js';
6
6
  import '@vaadin/vaadin-lumo-styles/font-icons.js';
7
+ import { fieldButton } from '@vaadin/vaadin-lumo-styles/mixins/field-button.js';
7
8
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
9
 
9
10
  export const sideNavItemStyles = css`
10
- [part='content'] {
11
- display: flex;
12
- align-items: center;
13
- }
14
-
15
11
  [part='link'] {
16
12
  width: 100%;
17
13
  gap: var(--lumo-space-xs);
@@ -23,19 +19,18 @@ export const sideNavItemStyles = css`
23
19
  min-height: var(--lumo-icon-size-m);
24
20
  }
25
21
 
22
+ [part='link'][href] {
23
+ cursor: pointer;
24
+ }
25
+
26
+ :host([disabled]) [part='link'] {
27
+ color: var(--lumo-disabled-text-color);
28
+ }
29
+
26
30
  [part='toggle-button'] {
27
- position: relative;
28
- border: 0;
29
- margin: calc((var(--lumo-icon-size-m) - var(--lumo-size-s)) / 2) 0;
30
31
  margin-inline-end: calc(var(--lumo-space-xs) * -1);
31
- padding: 0;
32
- background: transparent;
33
- font: inherit;
34
- color: var(--lumo-tertiary-text-color);
35
32
  width: var(--lumo-size-s);
36
33
  height: var(--lumo-size-s);
37
- cursor: var(--lumo-clickable-cursor, default);
38
- transition: color 140ms;
39
34
  }
40
35
 
41
36
  :host([has-children]) [part='content'] {
@@ -57,15 +52,15 @@ export const sideNavItemStyles = css`
57
52
  }
58
53
 
59
54
  [part='toggle-button']::before {
60
- font-family: lumo-icons;
61
55
  content: var(--lumo-icons-dropdown);
62
- font-size: 1.5em;
63
- line-height: var(--lumo-size-s);
64
- display: inline-block;
65
56
  transform: rotate(-90deg);
66
57
  transition: transform 140ms;
67
58
  }
68
59
 
60
+ :host([dir='rtl']) [part='toggle-button']::before {
61
+ transform: rotate(90deg);
62
+ }
63
+
69
64
  :host([expanded]) [part='toggle-button']::before {
70
65
  transform: none;
71
66
  }
@@ -93,10 +88,15 @@ export const sideNavItemStyles = css`
93
88
 
94
89
  slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
95
90
  padding: 0.1em;
91
+ flex-shrink: 0;
96
92
  color: var(--lumo-contrast-60pct);
97
93
  }
98
94
 
99
- :host([active]) slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
95
+ :host([disabled]) slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
96
+ color: var(--lumo-disabled-text-color);
97
+ }
98
+
99
+ :host([current]) slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
100
100
  color: inherit;
101
101
  }
102
102
 
@@ -108,10 +108,10 @@ export const sideNavItemStyles = css`
108
108
  --_child-indent-2: var(--_child-indent);
109
109
  }
110
110
 
111
- :host([active]) [part='link'] {
111
+ :host([current]) [part='link'] {
112
112
  color: var(--lumo-primary-text-color);
113
113
  background-color: var(--lumo-primary-color-10pct);
114
114
  }
115
115
  `;
116
116
 
117
- registerStyles('vaadin-side-nav-item', sideNavItemStyles, { moduleId: 'lumo-side-nav-item' });
117
+ registerStyles('vaadin-side-nav-item', [fieldButton, sideNavItemStyles], { moduleId: 'lumo-side-nav-item' });
@@ -55,16 +55,21 @@ export const sideNavStyles = css`
55
55
 
56
56
  [part='toggle-button']::before {
57
57
  content: var(--lumo-icons-angle-right);
58
+ transition: transform 140ms;
58
59
  }
59
60
 
60
61
  :host(:not([collapsible])) [part='toggle-button'] {
61
62
  display: none !important;
62
63
  }
63
64
 
64
- :host(:not([collapsed])) [part='toggle-button'] {
65
+ :host(:not([collapsed])) [part='toggle-button']::before {
65
66
  transform: rotate(90deg);
66
67
  }
67
68
 
69
+ :host([collapsed][dir='rtl']) [part='toggle-button']::before {
70
+ transform: rotate(180deg);
71
+ }
72
+
68
73
  @media (any-hover: hover) {
69
74
  [part='label']:hover [part='toggle-button'] {
70
75
  color: var(--lumo-body-text-color);
@@ -0,0 +1,142 @@
1
+ import '@vaadin/vaadin-material-styles/color.js';
2
+ import '@vaadin/vaadin-material-styles/font-icons.js';
3
+ import '@vaadin/vaadin-material-styles/typography.js';
4
+ import { fieldButton } from '@vaadin/vaadin-material-styles/mixins/field-button.js';
5
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
+
7
+ export const sideNavItemStyles = css`
8
+ [part='link'] {
9
+ position: relative;
10
+ width: 100%;
11
+ min-height: 32px;
12
+ margin: 4px 0;
13
+ gap: 8px;
14
+ padding: 4px 8px;
15
+ padding-inline-start: calc(8px + var(--_child-indent, 0px));
16
+ font-family: var(--material-font-family);
17
+ font-size: var(--material-small-font-size);
18
+ line-height: 1;
19
+ font-weight: 500;
20
+ color: var(--material-body-text-color);
21
+ transition: background-color 140ms, color 140ms;
22
+ border-radius: 4px;
23
+ cursor: default;
24
+ }
25
+
26
+ [part='link'][href] {
27
+ cursor: pointer;
28
+ }
29
+
30
+ :host([current]) [part='link'] {
31
+ color: var(--material-primary-text-color);
32
+ }
33
+
34
+ :host([disabled]) [part='link'] {
35
+ color: var(--material-disabled-text-color);
36
+ }
37
+
38
+ :host([current]) [part='link']::before {
39
+ position: absolute;
40
+ content: '';
41
+ inset: 0;
42
+ background-color: var(--material-primary-color);
43
+ opacity: 0.12;
44
+ border-radius: 4px;
45
+ }
46
+
47
+ [part='toggle-button'] {
48
+ width: 32px;
49
+ height: 32px;
50
+ margin-inline-end: -4px;
51
+ transform: rotate(90deg);
52
+ }
53
+
54
+ [part='toggle-button']::before {
55
+ font-family: 'material-icons';
56
+ font-size: 24px;
57
+ width: 24px;
58
+ display: inline-block;
59
+ content: var(--material-icons-chevron-right);
60
+ }
61
+
62
+ [part='toggle-button']::after {
63
+ display: inline-block;
64
+ content: '';
65
+ position: absolute;
66
+ top: 0;
67
+ left: 0;
68
+ width: 100%;
69
+ height: 100%;
70
+ border-radius: 50%;
71
+ background-color: var(--material-disabled-text-color);
72
+ transform: scale(0);
73
+ opacity: 0;
74
+ transition: transform 0s 0.8s, opacity 0.8s;
75
+ will-change: transform, opacity;
76
+ }
77
+
78
+ [part='toggle-button']:focus-visible::after {
79
+ transition-duration: 0.08s, 0.01s;
80
+ transition-delay: 0s, 0s;
81
+ transform: scale(1.25);
82
+ opacity: 0.16;
83
+ }
84
+
85
+ :host([expanded]) [part='toggle-button'] {
86
+ transform: rotate(270deg);
87
+ }
88
+
89
+ :host([has-children]) [part='content'] {
90
+ padding-inline-end: 8px;
91
+ }
92
+
93
+ @media (any-hover: hover) {
94
+ :host(:not([current])) [part='link'][href]:hover {
95
+ background-color: var(--material-secondary-background-color);
96
+ }
97
+
98
+ [part='toggle-button']:hover {
99
+ color: var(--material-body-text-color);
100
+ }
101
+ }
102
+
103
+ @supports selector(:focus-visible) {
104
+ [part='link'],
105
+ [part='toggle-button'] {
106
+ outline: none;
107
+ }
108
+
109
+ :host(:not([current])) [part='link']:focus-visible {
110
+ background-color: var(--material-divider-color);
111
+ }
112
+
113
+ :host([current]) [part='link']:focus-visible::before {
114
+ opacity: 0.24;
115
+ }
116
+ }
117
+
118
+ slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
119
+ padding: 0.1em;
120
+ flex-shrink: 0;
121
+ margin-inline-end: 24px;
122
+ color: var(--material-secondary-text-color);
123
+ }
124
+
125
+ :host([disabled]) slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
126
+ color: var(--material-disabled-text-color);
127
+ }
128
+
129
+ :host([current]) slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
130
+ color: inherit;
131
+ }
132
+
133
+ slot[name='children'] {
134
+ --_child-indent: calc(var(--_child-indent-2, 0px) + var(--vaadin-side-nav-child-indent, 24px));
135
+ }
136
+
137
+ slot[name='children']::slotted(*) {
138
+ --_child-indent-2: var(--_child-indent);
139
+ }
140
+ `;
141
+
142
+ registerStyles('vaadin-side-nav-item', [fieldButton, sideNavItemStyles], { moduleId: 'material-side-nav-item' });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import './vaadin-side-nav-item-styles.js';
7
+ import '../../src/vaadin-side-nav-item.js';
@@ -0,0 +1,69 @@
1
+ import '@vaadin/vaadin-material-styles/color.js';
2
+ import '@vaadin/vaadin-material-styles/font-icons.js';
3
+ import '@vaadin/vaadin-material-styles/typography.js';
4
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
5
+
6
+ export const sideNavStyles = css`
7
+ :host {
8
+ -webkit-tap-highlight-color: transparent;
9
+ outline: none;
10
+ }
11
+
12
+ [part='label'] {
13
+ display: flex;
14
+ align-items: center;
15
+ width: 100%;
16
+ min-height: 40px;
17
+ margin: 4px 0;
18
+ padding: 4px 8px;
19
+ outline: none;
20
+ box-sizing: border-box;
21
+ font-family: var(--material-font-family);
22
+ font-size: var(--material-small-font-size);
23
+ color: var(--material-secondary-text-color);
24
+ line-height: 1;
25
+ font-weight: 500;
26
+ border-radius: 4px;
27
+ }
28
+
29
+ :host([focus-ring]) [part='label'] {
30
+ background-color: var(--material-divider-color);
31
+ }
32
+
33
+ [part='toggle-button'] {
34
+ display: inline-flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ width: 24px;
38
+ height: 24px;
39
+ padding: 4px;
40
+ margin-inline-start: auto;
41
+ margin-inline-end: -4px;
42
+ font-size: var(--material-icon-font-size);
43
+ line-height: 1;
44
+ color: var(--material-secondary-text-color);
45
+ font-family: 'material-icons';
46
+ transform: rotate(90deg);
47
+ }
48
+
49
+ [part='toggle-button']::before {
50
+ content: var(--material-icons-chevron-right);
51
+ font-size: 24px;
52
+ }
53
+
54
+ :host(:not([collapsible])) [part='toggle-button'] {
55
+ display: none !important;
56
+ }
57
+
58
+ :host(:not([collapsed])) [part='toggle-button'] {
59
+ transform: rotate(270deg);
60
+ }
61
+
62
+ @media (any-hover: hover) {
63
+ [part='label']:hover [part='toggle-button'] {
64
+ color: var(--material-body-text-color);
65
+ }
66
+ }
67
+ `;
68
+
69
+ registerStyles('vaadin-side-nav', sideNavStyles, { moduleId: 'material-side-nav' });
@@ -3,5 +3,6 @@
3
3
  * Copyright (c) 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import './vaadin-side-nav-item.js';
7
+ import './vaadin-side-nav-styles.js';
6
8
  import '../../src/vaadin-side-nav.js';
7
- import '../../src/vaadin-side-nav-item.js';
package/web-types.json CHANGED
@@ -1,29 +1,29 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/side-nav",
4
- "version": "24.2.0-alpha1",
4
+ "version": "24.2.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-side-nav-item",
11
- "description": "A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.\nNot intended to be used separately.\n\n```html\n<vaadin-side-nav-item>\n Item 1\n <vaadin-side-nav-item path=\"/path1\" slot=\"children\">\n Child item 1\n </vaadin-side-nav-item>\n <vaadin-side-nav-item path=\"/path2\" slot=\"children\">\n Child item 2\n </vaadin-side-nav-item>\n</vaadin-side-nav-item>\n```\n\n### Customization\n\nYou can configure the item by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`prefix` | A slot for content before the label (e.g. an icon).\n`suffix` | A slot for content after the label (e.g. an icon).\n\n#### Example\n\n```html\n<vaadin-side-nav-item>\n <vaadin-icon icon=\"vaadin:chart\" slot=\"prefix\"></vaadin-icon>\n Item\n <span theme=\"badge primary\" slot=\"suffix\">Suffix</span>\n</vaadin-side-nav-item>\n```\n\n### Styling\n\nPart name | Description\n----------------|----------------\n`content` | The element that wraps link and toggle button\n`children` | The element that wraps child items\n`link` | The clickable anchor used for navigation\n`toggle-button` | The toggle button\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
11
+ "description": "A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.\nNot intended to be used separately.\n\n```html\n<vaadin-side-nav-item>\n Item 1\n <vaadin-side-nav-item path=\"/path1\" slot=\"children\">\n Child item 1\n </vaadin-side-nav-item>\n <vaadin-side-nav-item path=\"/path2\" slot=\"children\">\n Child item 2\n </vaadin-side-nav-item>\n</vaadin-side-nav-item>\n```\n\n### Customization\n\nYou can configure the item by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`prefix` | A slot for content before the label (e.g. an icon).\n`suffix` | A slot for content after the label (e.g. an icon).\n\n#### Example\n\n```html\n<vaadin-side-nav-item>\n <vaadin-icon icon=\"vaadin:chart\" slot=\"prefix\"></vaadin-icon>\n Item\n <span theme=\"badge primary\" slot=\"suffix\">Suffix</span>\n</vaadin-side-nav-item>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`content` | The element that wraps link and toggle button\n`children` | The element that wraps child items\n`link` | The clickable anchor used for navigation\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------|-------------\n`disabled` | Set when the element is disabled.\n`expanded` | Set when the element is expanded.\n`has-children` | Set when the element has child items.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
- "name": "path",
15
- "description": "The path to navigate to",
14
+ "name": "disabled",
15
+ "description": "If true, the user cannot interact with this element.",
16
16
  "value": {
17
17
  "type": [
18
- "string",
18
+ "boolean",
19
19
  "null",
20
20
  "undefined"
21
21
  ]
22
22
  }
23
23
  },
24
24
  {
25
- "name": "path-aliases",
26
- "description": "A comma-separated list of alternative paths matching this item.",
25
+ "name": "path",
26
+ "description": "The path to navigate to",
27
27
  "value": {
28
28
  "type": [
29
29
  "string",
@@ -55,6 +55,26 @@
55
55
  ],
56
56
  "js": {
57
57
  "properties": [
58
+ {
59
+ "name": "disabled",
60
+ "description": "If true, the user cannot interact with this element.",
61
+ "value": {
62
+ "type": [
63
+ "boolean",
64
+ "null",
65
+ "undefined"
66
+ ]
67
+ }
68
+ },
69
+ {
70
+ "name": "i18n",
71
+ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```",
72
+ "value": {
73
+ "type": [
74
+ "SideNavI18n"
75
+ ]
76
+ }
77
+ },
58
78
  {
59
79
  "name": "path",
60
80
  "description": "The path to navigate to",
@@ -68,12 +88,10 @@
68
88
  },
69
89
  {
70
90
  "name": "pathAliases",
71
- "description": "A comma-separated list of alternative paths matching this item.",
91
+ "description": "The list of alternative paths matching this item",
72
92
  "value": {
73
93
  "type": [
74
- "string",
75
- "null",
76
- "undefined"
94
+ "Array.<string>"
77
95
  ]
78
96
  }
79
97
  },
@@ -97,7 +115,7 @@
97
115
  },
98
116
  {
99
117
  "name": "vaadin-side-nav",
100
- "description": "`<vaadin-side-nav>` is a Web Component for navigation menus.\n\n```html\n<vaadin-side-nav>\n <vaadin-side-nav-item>Item 1</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 2</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 3</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 4</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Customization\n\nYou can configure the component by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`label` | The label (text) inside the side nav.\n\n#### Example\n\n```html\n<vaadin-side-nav>\n <span slot=\"label\">Main menu</span>\n <vaadin-side-nav-item>Item</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Styling\n\nPart name | Description\n----------------|----------------\n`label` | The label element\n`children` | The element that wraps child items\n`toggle-button` | The toggle button\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
118
+ "description": "`<vaadin-side-nav>` is a Web Component for navigation menus.\n\n```html\n<vaadin-side-nav>\n <vaadin-side-nav-item>Item 1</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 2</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 3</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 4</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Customization\n\nYou can configure the component by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`label` | The label (text) inside the side nav.\n\n#### Example\n\n```html\n<vaadin-side-nav>\n <span slot=\"label\">Main menu</span>\n <vaadin-side-nav-item>Item</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`label` | The label element\n`children` | The element that wraps child items\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-------------|-------------\n`collapsed` | Set when the element is collapsed.\n`focus-ring` | Set when the label is focused using the keyboard.\n`focused` | Set when the label is focused.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
101
119
  "attributes": [
102
120
  {
103
121
  "name": "collapsible",
@@ -131,6 +149,15 @@
131
149
  ],
132
150
  "js": {
133
151
  "properties": [
152
+ {
153
+ "name": "i18n",
154
+ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```",
155
+ "value": {
156
+ "type": [
157
+ "SideNavI18n"
158
+ ]
159
+ }
160
+ },
134
161
  {
135
162
  "name": "collapsible",
136
163
  "description": "Whether the side nav is collapsible. When enabled, the toggle icon is shown.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/side-nav",
4
- "version": "24.2.0-alpha1",
4
+ "version": "24.2.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,9 +16,16 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-side-nav-item",
19
- "description": "A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.\nNot intended to be used separately.\n\n```html\n<vaadin-side-nav-item>\n Item 1\n <vaadin-side-nav-item path=\"/path1\" slot=\"children\">\n Child item 1\n </vaadin-side-nav-item>\n <vaadin-side-nav-item path=\"/path2\" slot=\"children\">\n Child item 2\n </vaadin-side-nav-item>\n</vaadin-side-nav-item>\n```\n\n### Customization\n\nYou can configure the item by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`prefix` | A slot for content before the label (e.g. an icon).\n`suffix` | A slot for content after the label (e.g. an icon).\n\n#### Example\n\n```html\n<vaadin-side-nav-item>\n <vaadin-icon icon=\"vaadin:chart\" slot=\"prefix\"></vaadin-icon>\n Item\n <span theme=\"badge primary\" slot=\"suffix\">Suffix</span>\n</vaadin-side-nav-item>\n```\n\n### Styling\n\nPart name | Description\n----------------|----------------\n`content` | The element that wraps link and toggle button\n`children` | The element that wraps child items\n`link` | The clickable anchor used for navigation\n`toggle-button` | The toggle button\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
19
+ "description": "A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.\nNot intended to be used separately.\n\n```html\n<vaadin-side-nav-item>\n Item 1\n <vaadin-side-nav-item path=\"/path1\" slot=\"children\">\n Child item 1\n </vaadin-side-nav-item>\n <vaadin-side-nav-item path=\"/path2\" slot=\"children\">\n Child item 2\n </vaadin-side-nav-item>\n</vaadin-side-nav-item>\n```\n\n### Customization\n\nYou can configure the item by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`prefix` | A slot for content before the label (e.g. an icon).\n`suffix` | A slot for content after the label (e.g. an icon).\n\n#### Example\n\n```html\n<vaadin-side-nav-item>\n <vaadin-icon icon=\"vaadin:chart\" slot=\"prefix\"></vaadin-icon>\n Item\n <span theme=\"badge primary\" slot=\"suffix\">Suffix</span>\n</vaadin-side-nav-item>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`content` | The element that wraps link and toggle button\n`children` | The element that wraps child items\n`link` | The clickable anchor used for navigation\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------|-------------\n`disabled` | Set when the element is disabled.\n`expanded` | Set when the element is expanded.\n`has-children` | Set when the element has child items.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
+ {
23
+ "name": "?disabled",
24
+ "description": "If true, the user cannot interact with this element.",
25
+ "value": {
26
+ "kind": "expression"
27
+ }
28
+ },
22
29
  {
23
30
  "name": "?expanded",
24
31
  "description": "Whether to show the child items or not",
@@ -26,6 +33,13 @@
26
33
  "kind": "expression"
27
34
  }
28
35
  },
36
+ {
37
+ "name": ".i18n",
38
+ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```",
39
+ "value": {
40
+ "kind": "expression"
41
+ }
42
+ },
29
43
  {
30
44
  "name": ".path",
31
45
  "description": "The path to navigate to",
@@ -35,7 +49,7 @@
35
49
  },
36
50
  {
37
51
  "name": ".pathAliases",
38
- "description": "A comma-separated list of alternative paths matching this item.",
52
+ "description": "The list of alternative paths matching this item",
39
53
  "value": {
40
54
  "kind": "expression"
41
55
  }
@@ -51,7 +65,7 @@
51
65
  },
52
66
  {
53
67
  "name": "vaadin-side-nav",
54
- "description": "`<vaadin-side-nav>` is a Web Component for navigation menus.\n\n```html\n<vaadin-side-nav>\n <vaadin-side-nav-item>Item 1</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 2</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 3</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 4</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Customization\n\nYou can configure the component by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`label` | The label (text) inside the side nav.\n\n#### Example\n\n```html\n<vaadin-side-nav>\n <span slot=\"label\">Main menu</span>\n <vaadin-side-nav-item>Item</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Styling\n\nPart name | Description\n----------------|----------------\n`label` | The label element\n`children` | The element that wraps child items\n`toggle-button` | The toggle button\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
68
+ "description": "`<vaadin-side-nav>` is a Web Component for navigation menus.\n\n```html\n<vaadin-side-nav>\n <vaadin-side-nav-item>Item 1</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 2</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 3</vaadin-side-nav-item>\n <vaadin-side-nav-item>Item 4</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Customization\n\nYou can configure the component by using `slot` names.\n\nSlot name | Description\n----------|-------------\n`label` | The label (text) inside the side nav.\n\n#### Example\n\n```html\n<vaadin-side-nav>\n <span slot=\"label\">Main menu</span>\n <vaadin-side-nav-item>Item</vaadin-side-nav-item>\n</vaadin-side-nav>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`label` | The label element\n`children` | The element that wraps child items\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-------------|-------------\n`collapsed` | Set when the element is collapsed.\n`focus-ring` | Set when the label is focused using the keyboard.\n`focused` | Set when the label is focused.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
55
69
  "extension": true,
56
70
  "attributes": [
57
71
  {
@@ -68,6 +82,13 @@
68
82
  "kind": "expression"
69
83
  }
70
84
  },
85
+ {
86
+ "name": ".i18n",
87
+ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```",
88
+ "value": {
89
+ "kind": "expression"
90
+ }
91
+ },
71
92
  {
72
93
  "name": "@collapsed-changed",
73
94
  "description": "Fired when the `collapsed` property changes.",