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

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-alpha11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -20,7 +20,6 @@
20
20
  "module": "vaadin-side-nav.js",
21
21
  "type": "module",
22
22
  "files": [
23
- "enable.js",
24
23
  "src",
25
24
  "theme",
26
25
  "vaadin-*.d.ts",
@@ -35,15 +34,15 @@
35
34
  "web-component"
36
35
  ],
37
36
  "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",
37
+ "@vaadin/component-base": "24.2.0-alpha11",
38
+ "@vaadin/vaadin-lumo-styles": "24.2.0-alpha11",
39
+ "@vaadin/vaadin-material-styles": "24.2.0-alpha11",
40
+ "@vaadin/vaadin-themable-mixin": "24.2.0-alpha11",
42
41
  "lit": "^2.0.0"
43
42
  },
44
43
  "devDependencies": {
45
44
  "@esm-bundle/chai": "^4.3.4",
46
- "@vaadin/testing-helpers": "^0.4.2",
45
+ "@vaadin/testing-helpers": "^0.5.0",
47
46
  "lit": "^2.0.0",
48
47
  "sinon": "^13.0.2"
49
48
  },
@@ -51,5 +50,5 @@
51
50
  "web-types.json",
52
51
  "web-types.lit.json"
53
52
  ],
54
- "gitHead": "0dbb118320203ab6c0c07450a3e718815367589f"
53
+ "gitHead": "a958207d5f6a09ca0e2dcf9f62194b3f92c8766a"
55
54
  }
@@ -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,41 +5,14 @@
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';
14
-
15
- function isEnabled() {
16
- return window.Vaadin && window.Vaadin.featureFlags && !!window.Vaadin.featureFlags.sideNavComponent;
17
- }
18
-
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
- }
15
+ import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
43
16
 
44
17
  /**
45
18
  * A navigation item to be used within `<vaadin-side-nav>`. Represents a navigation target.
@@ -78,6 +51,8 @@ class ChildrenController extends SlotController {
78
51
  *
79
52
  * ### Styling
80
53
  *
54
+ * The following shadow DOM parts are available for styling:
55
+ *
81
56
  * Part name | Description
82
57
  * ----------------|----------------
83
58
  * `content` | The element that wraps link and toggle button
@@ -85,6 +60,14 @@ class ChildrenController extends SlotController {
85
60
  * `link` | The clickable anchor used for navigation
86
61
  * `toggle-button` | The toggle button
87
62
  *
63
+ * The following state attributes are available for styling:
64
+ *
65
+ * Attribute | Description
66
+ * ---------------|-------------
67
+ * `disabled` | Set when the element is disabled.
68
+ * `expanded` | Set when the element is expanded.
69
+ * `has-children` | Set when the element has child items.
70
+ *
88
71
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
89
72
  *
90
73
  * @fires {CustomEvent} expanded-changed - Fired when the `expanded` property changes.
@@ -92,9 +75,11 @@ class ChildrenController extends SlotController {
92
75
  * @extends LitElement
93
76
  * @mixes PolylitMixin
94
77
  * @mixes ThemableMixin
78
+ * @mixes DisabledMixin
95
79
  * @mixes ElementMixin
80
+ * @mixes SideNavChildrenMixin
96
81
  */
97
- class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
82
+ class SideNavItem extends SideNavChildrenMixin(DisabledMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
98
83
  static get is() {
99
84
  return 'vaadin-side-nav-item';
100
85
  }
@@ -107,11 +92,14 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
107
92
  path: String,
108
93
 
109
94
  /**
110
- * A comma-separated list of alternative paths matching this item.
95
+ * The list of alternative paths matching this item
111
96
  *
112
- * @attr {string} path-aliases
97
+ * @type {!Array<string>}
113
98
  */
114
- pathAliases: String,
99
+ pathAliases: {
100
+ type: Array,
101
+ value: () => [],
102
+ },
115
103
 
116
104
  /**
117
105
  * Whether to show the child items or not
@@ -132,7 +120,7 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
132
120
  *
133
121
  * @type {boolean}
134
122
  */
135
- active: {
123
+ current: {
136
124
  type: Boolean,
137
125
  value: false,
138
126
  readOnly: true,
@@ -142,13 +130,13 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
142
130
  }
143
131
 
144
132
  static get styles() {
145
- return sideNavItemBaseStyles;
133
+ return [screenReaderOnly, sideNavItemBaseStyles];
146
134
  }
147
135
 
148
136
  constructor() {
149
137
  super();
150
138
 
151
- this._childrenController = new ChildrenController(this);
139
+ this.__boundUpdateCurrent = this.__updateCurrent.bind(this);
152
140
  }
153
141
 
154
142
  /** @protected */
@@ -161,8 +149,7 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
161
149
  * @override
162
150
  */
163
151
  firstUpdated() {
164
- // Controller to detect whether the item has child items.
165
- this.addController(this._childrenController);
152
+ super.firstUpdated();
166
153
 
167
154
  // By default, if the user hasn't provided a custom role,
168
155
  // the role attribute is set to "listitem".
@@ -179,46 +166,60 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
179
166
  super.updated(props);
180
167
 
181
168
  if (props.has('path') || props.has('pathAliases')) {
182
- this.__updateActive();
169
+ this.__updateCurrent();
183
170
  }
184
171
 
185
- this.toggleAttribute('has-children', this._childrenController.nodes.length > 0);
172
+ // Ensure all the child items are disabled
173
+ if (props.has('disabled') || props.has('_itemsCount')) {
174
+ this._items.forEach((item) => {
175
+ item.disabled = this.disabled;
176
+ });
177
+ }
186
178
  }
187
179
 
188
180
  /** @protected */
189
181
  connectedCallback() {
190
182
  super.connectedCallback();
191
- this.__updateActive();
192
- this.__boundUpdateActive = this.__updateActive.bind(this);
193
- window.addEventListener('popstate', this.__boundUpdateActive);
183
+ this.__updateCurrent();
184
+
185
+ window.addEventListener('popstate', this.__boundUpdateCurrent);
194
186
  }
195
187
 
196
188
  /** @protected */
197
189
  disconnectedCallback() {
198
190
  super.disconnectedCallback();
199
- window.removeEventListener('popstate', this.__boundUpdateActive);
191
+ window.removeEventListener('popstate', this.__boundUpdateCurrent);
200
192
  }
201
193
 
202
194
  /** @protected */
203
195
  render() {
204
196
  return html`
205
197
  <div part="content" @click="${this._onContentClick}">
206
- <a href="${ifDefined(this.path)}" part="link" aria-current="${this.active ? 'page' : 'false'}">
198
+ <a
199
+ id="link"
200
+ ?disabled="${this.disabled}"
201
+ tabindex="${this.disabled || !this.path ? '-1' : '0'}"
202
+ href="${ifDefined(this.disabled ? null : this.path)}"
203
+ part="link"
204
+ aria-current="${this.current ? 'page' : 'false'}"
205
+ >
207
206
  <slot name="prefix"></slot>
208
207
  <slot></slot>
209
208
  <slot name="suffix"></slot>
210
209
  </a>
211
210
  <button
212
211
  part="toggle-button"
212
+ ?disabled="${this.disabled}"
213
213
  @click="${this._onButtonClick}"
214
214
  aria-controls="children"
215
215
  aria-expanded="${this.expanded}"
216
- aria-label="Toggle child items"
216
+ aria-labelledby="link i18n"
217
217
  ></button>
218
218
  </div>
219
- <ul part="children" ?hidden="${!this.expanded}">
219
+ <ul part="children" role="list" ?hidden="${!this.expanded}" aria-hidden="${this.expanded ? 'false' : 'true'}">
220
220
  <slot name="children"></slot>
221
221
  </ul>
222
+ <div class="sr-only" id="i18n">${this.i18n.toggle}</div>
222
223
  `;
223
224
  }
224
225
 
@@ -244,35 +245,25 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
244
245
  }
245
246
 
246
247
  /** @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;
248
+ __updateCurrent() {
249
+ this._setCurrent(this.__isCurrent());
250
+ if (this.current) {
251
+ this.expanded = this._items.length > 0;
256
252
  }
257
253
  }
258
254
 
259
255
  /** @private */
260
- __calculateActive() {
256
+ __isCurrent() {
261
257
  if (this.path == null) {
262
258
  return false;
263
259
  }
264
- if (matchPaths(document.location.pathname, this.path)) {
265
- return true;
266
- }
267
260
  return (
268
- this.pathAliases != null &&
269
- this.pathAliases.split(',').some((alias) => matchPaths(document.location.pathname, alias))
261
+ matchPaths(document.location.pathname, this.path) ||
262
+ this.pathAliases.some((alias) => matchPaths(document.location.pathname, alias))
270
263
  );
271
264
  }
272
265
  }
273
266
 
274
- if (isEnabled()) {
275
- customElements.define(SideNavItem.is, SideNavItem);
276
- }
267
+ customElements.define(SideNavItem.is, SideNavItem);
277
268
 
278
269
  export { SideNavItem };
@@ -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,10 +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
-
15
- function isEnabled() {
16
- return window.Vaadin && window.Vaadin.featureFlags && !!window.Vaadin.featureFlags.sideNavComponent;
17
- }
14
+ import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
18
15
 
19
16
  /**
20
17
  * `<vaadin-side-nav>` is a Web Component for navigation menus.
@@ -47,12 +44,22 @@ function isEnabled() {
47
44
  *
48
45
  * ### Styling
49
46
  *
47
+ * The following shadow DOM parts are available for styling:
48
+ *
50
49
  * Part name | Description
51
50
  * ----------------|----------------
52
51
  * `label` | The label element
53
52
  * `children` | The element that wraps child items
54
53
  * `toggle-button` | The toggle button
55
54
  *
55
+ * The following state attributes are available for styling:
56
+ *
57
+ * Attribute | Description
58
+ * -------------|-------------
59
+ * `collapsed` | Set when the element is collapsed.
60
+ * `focus-ring` | Set when the label is focused using the keyboard.
61
+ * `focused` | Set when the label is focused.
62
+ *
56
63
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
57
64
  *
58
65
  * @fires {CustomEvent} collapsed-changed - Fired when the `collapsed` property changes.
@@ -61,8 +68,9 @@ function isEnabled() {
61
68
  * @mixes PolylitMixin
62
69
  * @mixes ThemableMixin
63
70
  * @mixes ElementMixin
71
+ * @mixes SideNavChildrenMixin
64
72
  */
65
- class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
73
+ class SideNav extends SideNavChildrenMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
66
74
  static get is() {
67
75
  return 'vaadin-side-nav';
68
76
  }
@@ -108,6 +116,15 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
108
116
  this._labelId = `side-nav-label-${generateUniqueId()}`;
109
117
  }
110
118
 
119
+ /**
120
+ * Name of the slot to be used for children.
121
+ * @protected
122
+ * @override
123
+ */
124
+ get _itemsSlotName() {
125
+ return '';
126
+ }
127
+
111
128
  /** @protected */
112
129
  get focusElement() {
113
130
  return this.shadowRoot.querySelector('button');
@@ -115,6 +132,8 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
115
132
 
116
133
  /** @protected */
117
134
  firstUpdated() {
135
+ super.firstUpdated();
136
+
118
137
  // By default, if the user hasn't provided a custom role,
119
138
  // the role attribute is set to "navigation".
120
139
  if (!this.hasAttribute('role')) {
@@ -129,12 +148,19 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
129
148
  part="label"
130
149
  @click="${this._onLabelClick}"
131
150
  aria-expanded="${ifDefined(this.collapsible ? !this.collapsed : null)}"
151
+ aria-hidden="${ifDefined(this.collapsible === false ? true : null)}"
132
152
  aria-controls="children"
133
153
  >
134
154
  <slot name="label" @slotchange="${this._onLabelSlotChange}"></slot>
135
155
  <span part="toggle-button" aria-hidden="true"></span>
136
156
  </button>
137
- <ul id="children" part="children" ?hidden="${this.collapsed}" aria-hidden="${this.collapsed ? 'true' : 'false'}">
157
+ <ul
158
+ id="children"
159
+ role="list"
160
+ part="children"
161
+ ?hidden="${this.collapsed}"
162
+ aria-hidden="${this.collapsed ? 'true' : 'false'}"
163
+ >
138
164
  <slot></slot>
139
165
  </ul>
140
166
  `;
@@ -176,12 +202,6 @@ class SideNav extends FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElem
176
202
  }
177
203
  }
178
204
 
179
- if (isEnabled()) {
180
- customElements.define(SideNav.is, SideNav);
181
- } else {
182
- console.warn(
183
- 'WARNING: The side-nav component is currently an experimental feature and needs to be explicitly enabled. To enable the component, `import "@vaadin/side-nav/enable.js"` *before* importing the side-nav module itself.',
184
- );
185
- }
205
+ customElements.define(SideNav.is, SideNav);
186
206
 
187
207
  export { SideNav };
@@ -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-alpha11",
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-alpha11",
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.",
package/enable.js DELETED
@@ -1,3 +0,0 @@
1
- window.Vaadin ||= {};
2
- window.Vaadin.featureFlags ||= {};
3
- window.Vaadin.featureFlags.sideNavComponent = true;