@vaadin/side-nav 24.1.2 → 24.2.0-alpha2
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 +6 -1
- package/package.json +6 -6
- package/src/vaadin-side-nav-base-styles.js +36 -33
- package/src/vaadin-side-nav-children-mixin.d.ts +41 -0
- package/src/vaadin-side-nav-children-mixin.js +134 -0
- package/src/vaadin-side-nav-item.d.ts +29 -3
- package/src/vaadin-side-nav-item.js +93 -48
- package/src/vaadin-side-nav.d.ts +25 -1
- package/src/vaadin-side-nav.js +88 -17
- package/theme/lumo/vaadin-side-nav-item-styles.js +28 -28
- package/theme/lumo/vaadin-side-nav-item.js +1 -1
- package/theme/lumo/vaadin-side-nav-styles.js +35 -26
- package/theme/lumo/vaadin-side-nav.js +1 -1
- package/theme/material/vaadin-side-nav-item-styles.js +134 -0
- package/theme/material/vaadin-side-nav-item.js +7 -0
- package/theme/material/vaadin-side-nav-styles.js +69 -0
- package/theme/material/vaadin-side-nav.js +3 -2
- package/web-types.json +30 -3
- package/web-types.lit.json +24 -3
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.
|
|
3
|
+
"version": "24.2.0-alpha2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"web-component"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@vaadin/component-base": "
|
|
39
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
40
|
-
"@vaadin/vaadin-material-styles": "
|
|
41
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
38
|
+
"@vaadin/component-base": "24.2.0-alpha2",
|
|
39
|
+
"@vaadin/vaadin-lumo-styles": "24.2.0-alpha2",
|
|
40
|
+
"@vaadin/vaadin-material-styles": "24.2.0-alpha2",
|
|
41
|
+
"@vaadin/vaadin-themable-mixin": "24.2.0-alpha2",
|
|
42
42
|
"lit": "^2.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"web-types.json",
|
|
52
52
|
"web-types.lit.json"
|
|
53
53
|
],
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "b8378bd2267728e172012bcb2ea45c3e5a6e590a"
|
|
55
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c)
|
|
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
6
|
import { css } from 'lit';
|
|
@@ -10,11 +10,17 @@ 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
|
|
|
17
|
-
|
|
18
|
+
[part='content'] {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[part='link'] {
|
|
18
24
|
flex: auto;
|
|
19
25
|
min-width: 0;
|
|
20
26
|
display: flex;
|
|
@@ -28,10 +34,21 @@ export const sideNavItemBaseStyles = css`
|
|
|
28
34
|
-webkit-appearance: none;
|
|
29
35
|
appearance: none;
|
|
30
36
|
flex: none;
|
|
37
|
+
position: relative;
|
|
38
|
+
margin: 0;
|
|
39
|
+
padding: 0;
|
|
40
|
+
border: 0;
|
|
41
|
+
background: transparent;
|
|
31
42
|
}
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
[part='children'] {
|
|
45
|
+
padding: 0;
|
|
46
|
+
margin: 0;
|
|
47
|
+
list-style-type: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:host(:not([has-children])) button {
|
|
51
|
+
display: none !important;
|
|
35
52
|
}
|
|
36
53
|
|
|
37
54
|
:host(:not([path])) button::after {
|
|
@@ -56,12 +73,6 @@ export const sideNavItemBaseStyles = css`
|
|
|
56
73
|
text-overflow: ellipsis;
|
|
57
74
|
white-space: nowrap;
|
|
58
75
|
}
|
|
59
|
-
|
|
60
|
-
slot[name='children'] {
|
|
61
|
-
/* Needed to make role="list" work */
|
|
62
|
-
display: block;
|
|
63
|
-
width: 100%;
|
|
64
|
-
}
|
|
65
76
|
`;
|
|
66
77
|
|
|
67
78
|
export const sideNavBaseStyles = css`
|
|
@@ -73,32 +84,24 @@ export const sideNavBaseStyles = css`
|
|
|
73
84
|
display: none !important;
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
|
|
87
|
+
button {
|
|
77
88
|
display: flex;
|
|
78
89
|
align-items: center;
|
|
79
|
-
justify-content:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
summary::marker {
|
|
91
|
-
content: '';
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
summary::after {
|
|
95
|
-
display: inline-flex;
|
|
96
|
-
align-items: center;
|
|
97
|
-
justify-content: center;
|
|
90
|
+
justify-content: inherit;
|
|
91
|
+
width: 100%;
|
|
92
|
+
margin: 0;
|
|
93
|
+
padding: 0;
|
|
94
|
+
background-color: initial;
|
|
95
|
+
color: inherit;
|
|
96
|
+
border: initial;
|
|
97
|
+
outline: none;
|
|
98
|
+
font: inherit;
|
|
99
|
+
text-align: inherit;
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
[part='children'] {
|
|
103
|
+
padding: 0;
|
|
104
|
+
margin: 0;
|
|
105
|
+
list-style-type: none;
|
|
103
106
|
}
|
|
104
107
|
`;
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
}
|
|
@@ -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
|
+
* @private
|
|
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
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c)
|
|
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
6
|
import { LitElement } from 'lit';
|
|
7
7
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
8
8
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
9
9
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
10
|
+
import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Fired when the `expanded` property changes.
|
|
@@ -54,14 +55,39 @@ export type SideNavItemEventMap = HTMLElementEventMap & SideNavItemCustomEventMa
|
|
|
54
55
|
* </vaadin-side-nav-item>
|
|
55
56
|
* ```
|
|
56
57
|
*
|
|
58
|
+
* ### Styling
|
|
59
|
+
*
|
|
60
|
+
* The following shadow DOM parts are available for styling:
|
|
61
|
+
*
|
|
62
|
+
* Part name | Description
|
|
63
|
+
* ----------------|----------------
|
|
64
|
+
* `content` | The element that wraps link and toggle button
|
|
65
|
+
* `children` | The element that wraps child items
|
|
66
|
+
* `link` | The clickable anchor used for navigation
|
|
67
|
+
* `toggle-button` | The toggle button
|
|
68
|
+
*
|
|
69
|
+
* The following state attributes are available for styling:
|
|
70
|
+
*
|
|
71
|
+
* Attribute | Description
|
|
72
|
+
* ---------------|-------------
|
|
73
|
+
* `expanded` | Set when the element is expanded.
|
|
74
|
+
* `has-children` | Set when the element has child items.
|
|
75
|
+
*
|
|
76
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
77
|
+
*
|
|
57
78
|
* @fires {CustomEvent} expanded-changed - Fired when the `expanded` property changes.
|
|
58
79
|
*/
|
|
59
|
-
declare class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
80
|
+
declare class SideNavItem extends SideNavChildrenMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
60
81
|
/**
|
|
61
82
|
* The path to navigate to
|
|
62
83
|
*/
|
|
63
84
|
path: string | null | undefined;
|
|
64
85
|
|
|
86
|
+
/**
|
|
87
|
+
* The list of alternative paths matching this item
|
|
88
|
+
*/
|
|
89
|
+
pathAliases: string[];
|
|
90
|
+
|
|
65
91
|
/**
|
|
66
92
|
* Whether to show the child items or not
|
|
67
93
|
*/
|
|
@@ -72,7 +98,7 @@ declare class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitEle
|
|
|
72
98
|
* Set when the item is appended to DOM or when navigated back
|
|
73
99
|
* to the page that contains this item using the browser.
|
|
74
100
|
*/
|
|
75
|
-
readonly
|
|
101
|
+
readonly current: boolean;
|
|
76
102
|
|
|
77
103
|
addEventListener<K extends keyof SideNavItemEventMap>(
|
|
78
104
|
type: K,
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c)
|
|
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
6
|
import { html, LitElement } from 'lit';
|
|
7
7
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
8
|
+
import { screenReaderOnly } from '@vaadin/a11y-base/src/styles/sr-only-styles.js';
|
|
8
9
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
9
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
11
|
+
import { matchPaths } from '@vaadin/component-base/src/url-utils.js';
|
|
10
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
11
13
|
import { sideNavItemBaseStyles } from './vaadin-side-nav-base-styles.js';
|
|
14
|
+
import { SideNavChildrenMixin } from './vaadin-side-nav-children-mixin.js';
|
|
12
15
|
|
|
13
16
|
function isEnabled() {
|
|
14
17
|
return window.Vaadin && window.Vaadin.featureFlags && !!window.Vaadin.featureFlags.sideNavComponent;
|
|
@@ -49,14 +52,35 @@ function isEnabled() {
|
|
|
49
52
|
* </vaadin-side-nav-item>
|
|
50
53
|
* ```
|
|
51
54
|
*
|
|
55
|
+
* ### Styling
|
|
56
|
+
*
|
|
57
|
+
* The following shadow DOM parts are available for styling:
|
|
58
|
+
*
|
|
59
|
+
* Part name | Description
|
|
60
|
+
* ----------------|----------------
|
|
61
|
+
* `content` | The element that wraps link and toggle button
|
|
62
|
+
* `children` | The element that wraps child items
|
|
63
|
+
* `link` | The clickable anchor used for navigation
|
|
64
|
+
* `toggle-button` | The toggle button
|
|
65
|
+
*
|
|
66
|
+
* The following state attributes are available for styling:
|
|
67
|
+
*
|
|
68
|
+
* Attribute | Description
|
|
69
|
+
* ---------------|-------------
|
|
70
|
+
* `expanded` | Set when the element is expanded.
|
|
71
|
+
* `has-children` | Set when the element has child items.
|
|
72
|
+
*
|
|
73
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
74
|
+
*
|
|
52
75
|
* @fires {CustomEvent} expanded-changed - Fired when the `expanded` property changes.
|
|
53
76
|
*
|
|
54
77
|
* @extends LitElement
|
|
55
78
|
* @mixes PolylitMixin
|
|
56
79
|
* @mixes ThemableMixin
|
|
57
80
|
* @mixes ElementMixin
|
|
81
|
+
* @mixes SideNavChildrenMixin
|
|
58
82
|
*/
|
|
59
|
-
class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
83
|
+
class SideNavItem extends SideNavChildrenMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
60
84
|
static get is() {
|
|
61
85
|
return 'vaadin-side-nav-item';
|
|
62
86
|
}
|
|
@@ -68,6 +92,16 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
|
|
|
68
92
|
*/
|
|
69
93
|
path: String,
|
|
70
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The list of alternative paths matching this item
|
|
97
|
+
*
|
|
98
|
+
* @type {!Array<string>}
|
|
99
|
+
*/
|
|
100
|
+
pathAliases: {
|
|
101
|
+
type: Array,
|
|
102
|
+
value: () => [],
|
|
103
|
+
},
|
|
104
|
+
|
|
71
105
|
/**
|
|
72
106
|
* Whether to show the child items or not
|
|
73
107
|
*
|
|
@@ -87,7 +121,7 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
|
|
|
87
121
|
*
|
|
88
122
|
* @type {boolean}
|
|
89
123
|
*/
|
|
90
|
-
|
|
124
|
+
current: {
|
|
91
125
|
type: Boolean,
|
|
92
126
|
value: false,
|
|
93
127
|
readOnly: true,
|
|
@@ -97,7 +131,13 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
|
|
|
97
131
|
}
|
|
98
132
|
|
|
99
133
|
static get styles() {
|
|
100
|
-
return sideNavItemBaseStyles;
|
|
134
|
+
return [screenReaderOnly, sideNavItemBaseStyles];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
constructor() {
|
|
138
|
+
super();
|
|
139
|
+
|
|
140
|
+
this.__boundUpdateCurrent = this.__updateCurrent.bind(this);
|
|
101
141
|
}
|
|
102
142
|
|
|
103
143
|
/** @protected */
|
|
@@ -110,6 +150,8 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
|
|
|
110
150
|
* @override
|
|
111
151
|
*/
|
|
112
152
|
firstUpdated() {
|
|
153
|
+
super.firstUpdated();
|
|
154
|
+
|
|
113
155
|
// By default, if the user hasn't provided a custom role,
|
|
114
156
|
// the role attribute is set to "listitem".
|
|
115
157
|
if (!this.hasAttribute('role')) {
|
|
@@ -124,84 +166,87 @@ class SideNavItem extends ElementMixin(ThemableMixin(PolylitMixin(LitElement)))
|
|
|
124
166
|
updated(props) {
|
|
125
167
|
super.updated(props);
|
|
126
168
|
|
|
127
|
-
if (props.has('path')) {
|
|
128
|
-
this.
|
|
169
|
+
if (props.has('path') || props.has('pathAliases')) {
|
|
170
|
+
this.__updateCurrent();
|
|
129
171
|
}
|
|
130
172
|
}
|
|
131
173
|
|
|
132
174
|
/** @protected */
|
|
133
175
|
connectedCallback() {
|
|
134
176
|
super.connectedCallback();
|
|
135
|
-
this.
|
|
136
|
-
|
|
137
|
-
window.addEventListener('popstate', this.
|
|
177
|
+
this.__updateCurrent();
|
|
178
|
+
|
|
179
|
+
window.addEventListener('popstate', this.__boundUpdateCurrent);
|
|
138
180
|
}
|
|
139
181
|
|
|
140
182
|
/** @protected */
|
|
141
183
|
disconnectedCallback() {
|
|
142
184
|
super.disconnectedCallback();
|
|
143
|
-
window.removeEventListener('popstate', this.
|
|
185
|
+
window.removeEventListener('popstate', this.__boundUpdateCurrent);
|
|
144
186
|
}
|
|
145
187
|
|
|
146
188
|
/** @protected */
|
|
147
189
|
render() {
|
|
148
190
|
return html`
|
|
149
|
-
<
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
191
|
+
<div part="content" @click="${this._onContentClick}">
|
|
192
|
+
<a id="link" href="${ifDefined(this.path)}" part="link" aria-current="${this.current ? 'page' : 'false'}">
|
|
193
|
+
<slot name="prefix"></slot>
|
|
194
|
+
<slot></slot>
|
|
195
|
+
<slot name="suffix"></slot>
|
|
196
|
+
</a>
|
|
153
197
|
<button
|
|
154
198
|
part="toggle-button"
|
|
155
|
-
@click="${this.
|
|
156
|
-
?hidden="${!this.querySelector('[slot=children]')}"
|
|
199
|
+
@click="${this._onButtonClick}"
|
|
157
200
|
aria-controls="children"
|
|
158
201
|
aria-expanded="${this.expanded}"
|
|
159
|
-
aria-
|
|
202
|
+
aria-labelledby="link i18n"
|
|
160
203
|
></button>
|
|
161
|
-
</
|
|
162
|
-
<
|
|
204
|
+
</div>
|
|
205
|
+
<ul part="children" ?hidden="${!this.expanded}">
|
|
206
|
+
<slot name="children"></slot>
|
|
207
|
+
</ul>
|
|
208
|
+
<div class="sr-only" id="i18n">${this.i18n.toggle}</div>
|
|
163
209
|
`;
|
|
164
210
|
}
|
|
165
211
|
|
|
166
212
|
/** @private */
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
213
|
+
_onButtonClick(event) {
|
|
214
|
+
// Prevent the event from being handled
|
|
215
|
+
// by the content click listener below
|
|
216
|
+
event.stopPropagation();
|
|
217
|
+
this.__toggleExpanded();
|
|
171
218
|
}
|
|
172
219
|
|
|
173
220
|
/** @private */
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
this._setActive(this.__calculateActive());
|
|
180
|
-
this.toggleAttribute('child-active', document.location.pathname.startsWith(this.path));
|
|
181
|
-
if (this.active) {
|
|
182
|
-
this.expanded = true;
|
|
221
|
+
_onContentClick() {
|
|
222
|
+
// Toggle item expanded state unless the link has a non-empty path
|
|
223
|
+
if (this.path == null && this.hasAttribute('has-children')) {
|
|
224
|
+
this.__toggleExpanded();
|
|
183
225
|
}
|
|
184
226
|
}
|
|
185
227
|
|
|
186
228
|
/** @private */
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
229
|
+
__toggleExpanded() {
|
|
230
|
+
this.expanded = !this.expanded;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** @private */
|
|
234
|
+
__updateCurrent() {
|
|
235
|
+
this._setCurrent(this.__isCurrent());
|
|
236
|
+
if (this.current) {
|
|
237
|
+
this.expanded = this._items.length > 0;
|
|
193
238
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** @private */
|
|
242
|
+
__isCurrent() {
|
|
243
|
+
if (this.path == null) {
|
|
244
|
+
return false;
|
|
198
245
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
basePath !== pathRelativeToRoot && pathRelativeToRoot.startsWith(basePath) ? pathWithoutBase : pathRelativeToRoot;
|
|
204
|
-
return pathRelativeToBase === this.path;
|
|
246
|
+
return (
|
|
247
|
+
matchPaths(document.location.pathname, this.path) ||
|
|
248
|
+
this.pathAliases.some((alias) => matchPaths(document.location.pathname, alias))
|
|
249
|
+
);
|
|
205
250
|
}
|
|
206
251
|
}
|
|
207
252
|
|
package/src/vaadin-side-nav.d.ts
CHANGED
|
@@ -4,9 +4,13 @@
|
|
|
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 { FocusMixin } from '@vaadin/a11y-base/src/focus-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, type SideNavI18n } from './vaadin-side-nav-children-mixin.js';
|
|
12
|
+
|
|
13
|
+
export type { SideNavI18n };
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* Fired when the `collapsed` property changes.
|
|
@@ -48,9 +52,29 @@ export type SideNavEventMap = HTMLElementEventMap & SideNavCustomEventMap;
|
|
|
48
52
|
* </vaadin-side-nav>
|
|
49
53
|
* ```
|
|
50
54
|
*
|
|
55
|
+
* ### Styling
|
|
56
|
+
*
|
|
57
|
+
* The following shadow DOM parts are available for styling:
|
|
58
|
+
*
|
|
59
|
+
* Part name | Description
|
|
60
|
+
* ----------------|----------------
|
|
61
|
+
* `label` | The label element
|
|
62
|
+
* `children` | The element that wraps child items
|
|
63
|
+
* `toggle-button` | The toggle button
|
|
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
|
+
*
|
|
73
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
74
|
+
*
|
|
51
75
|
* @fires {CustomEvent} collapsed-changed - Fired when the `collapsed` property changes.
|
|
52
76
|
*/
|
|
53
|
-
declare class SideNav extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
77
|
+
declare class SideNav extends SideNavChildrenMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
|
|
54
78
|
/**
|
|
55
79
|
* Whether the side nav is collapsible. When enabled, the toggle icon is shown.
|
|
56
80
|
*/
|