@vaadin/side-nav 24.1.5 → 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 +6 -1
- package/package.json +7 -7
- package/src/vaadin-side-nav-base-styles.js +38 -40
- package/src/vaadin-side-nav-children-mixin.d.ts +46 -0
- package/src/vaadin-side-nav-children-mixin.js +134 -0
- package/src/vaadin-side-nav-item.d.ts +33 -3
- package/src/vaadin-side-nav-item.js +111 -48
- package/src/vaadin-side-nav.d.ts +25 -1
- package/src/vaadin-side-nav.js +95 -17
- package/theme/lumo/vaadin-side-nav-item-styles.js +40 -28
- package/theme/lumo/vaadin-side-nav-item.js +1 -1
- package/theme/lumo/vaadin-side-nav-styles.js +39 -25
- package/theme/lumo/vaadin-side-nav.js +1 -1
- package/theme/material/vaadin-side-nav-item-styles.js +142 -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 +52 -3
- package/web-types.lit.json +31 -3
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
|
*/
|
package/src/vaadin-side-nav.js
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
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
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
8
|
+
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
7
9
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
8
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
9
11
|
import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
|
|
10
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
11
13
|
import { sideNavBaseStyles } 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;
|
|
@@ -43,18 +46,43 @@ function isEnabled() {
|
|
|
43
46
|
* </vaadin-side-nav>
|
|
44
47
|
* ```
|
|
45
48
|
*
|
|
49
|
+
* ### Styling
|
|
50
|
+
*
|
|
51
|
+
* The following shadow DOM parts are available for styling:
|
|
52
|
+
*
|
|
53
|
+
* Part name | Description
|
|
54
|
+
* ----------------|----------------
|
|
55
|
+
* `label` | The label element
|
|
56
|
+
* `children` | The element that wraps child items
|
|
57
|
+
* `toggle-button` | The toggle button
|
|
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
|
+
*
|
|
67
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
68
|
+
*
|
|
46
69
|
* @fires {CustomEvent} collapsed-changed - Fired when the `collapsed` property changes.
|
|
47
70
|
*
|
|
48
71
|
* @extends LitElement
|
|
49
72
|
* @mixes PolylitMixin
|
|
50
73
|
* @mixes ThemableMixin
|
|
51
74
|
* @mixes ElementMixin
|
|
75
|
+
* @mixes SideNavChildrenMixin
|
|
52
76
|
*/
|
|
53
|
-
class SideNav extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
77
|
+
class SideNav extends SideNavChildrenMixin(FocusMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
|
|
54
78
|
static get is() {
|
|
55
79
|
return 'vaadin-side-nav';
|
|
56
80
|
}
|
|
57
81
|
|
|
82
|
+
static get shadowRootOptions() {
|
|
83
|
+
return { ...LitElement.shadowRootOptions, delegatesFocus: true };
|
|
84
|
+
}
|
|
85
|
+
|
|
58
86
|
static get properties() {
|
|
59
87
|
return {
|
|
60
88
|
/**
|
|
@@ -86,8 +114,30 @@ class SideNav extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
|
86
114
|
return sideNavBaseStyles;
|
|
87
115
|
}
|
|
88
116
|
|
|
117
|
+
constructor() {
|
|
118
|
+
super();
|
|
119
|
+
|
|
120
|
+
this._labelId = `side-nav-label-${generateUniqueId()}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Name of the slot to be used for children.
|
|
125
|
+
* @protected
|
|
126
|
+
* @override
|
|
127
|
+
*/
|
|
128
|
+
get _itemsSlotName() {
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** @protected */
|
|
133
|
+
get focusElement() {
|
|
134
|
+
return this.shadowRoot.querySelector('button');
|
|
135
|
+
}
|
|
136
|
+
|
|
89
137
|
/** @protected */
|
|
90
138
|
firstUpdated() {
|
|
139
|
+
super.firstUpdated();
|
|
140
|
+
|
|
91
141
|
// By default, if the user hasn't provided a custom role,
|
|
92
142
|
// the role attribute is set to "navigation".
|
|
93
143
|
if (!this.hasAttribute('role')) {
|
|
@@ -97,34 +147,62 @@ class SideNav extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
|
97
147
|
|
|
98
148
|
/** @protected */
|
|
99
149
|
render() {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
150
|
+
return html`
|
|
151
|
+
<button
|
|
152
|
+
part="label"
|
|
153
|
+
@click="${this._onLabelClick}"
|
|
154
|
+
aria-expanded="${ifDefined(this.collapsible ? !this.collapsed : null)}"
|
|
155
|
+
aria-hidden="${ifDefined(this.collapsible === false ? true : null)}"
|
|
156
|
+
aria-controls="children"
|
|
157
|
+
>
|
|
158
|
+
<slot name="label" @slotchange="${this._onLabelSlotChange}"></slot>
|
|
159
|
+
<span part="toggle-button" aria-hidden="true"></span>
|
|
160
|
+
</button>
|
|
161
|
+
<ul
|
|
162
|
+
id="children"
|
|
163
|
+
role="list"
|
|
164
|
+
part="children"
|
|
165
|
+
?hidden="${this.collapsed}"
|
|
166
|
+
aria-hidden="${this.collapsed ? 'true' : 'false'}"
|
|
167
|
+
>
|
|
168
|
+
<slot></slot>
|
|
169
|
+
</ul>
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {Event} event
|
|
175
|
+
* @return {boolean}
|
|
176
|
+
* @protected
|
|
177
|
+
* @override
|
|
178
|
+
*/
|
|
179
|
+
_shouldSetFocus(event) {
|
|
180
|
+
return event.composedPath()[0] === this.focusElement;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** @private */
|
|
184
|
+
_onLabelClick() {
|
|
185
|
+
if (this.collapsible) {
|
|
186
|
+
this.__toggleCollapsed();
|
|
105
187
|
}
|
|
106
|
-
return this.__renderBody(label);
|
|
107
188
|
}
|
|
108
189
|
|
|
109
190
|
/** @private */
|
|
110
|
-
|
|
191
|
+
_onLabelSlotChange() {
|
|
192
|
+
const label = this.querySelector('[slot="label"]');
|
|
111
193
|
if (label) {
|
|
112
|
-
if (!label.id)
|
|
194
|
+
if (!label.id) {
|
|
195
|
+
label.id = this._labelId;
|
|
196
|
+
}
|
|
113
197
|
this.setAttribute('aria-labelledby', label.id);
|
|
114
198
|
} else {
|
|
115
199
|
this.removeAttribute('aria-labelledby');
|
|
116
200
|
}
|
|
117
|
-
return html`
|
|
118
|
-
<summary part="label" ?hidden="${label == null}">
|
|
119
|
-
<slot name="label" @slotchange="${() => this.requestUpdate()}"></slot>
|
|
120
|
-
</summary>
|
|
121
|
-
<slot role="list"></slot>
|
|
122
|
-
`;
|
|
123
201
|
}
|
|
124
202
|
|
|
125
203
|
/** @private */
|
|
126
|
-
__toggleCollapsed(
|
|
127
|
-
this.collapsed = !
|
|
204
|
+
__toggleCollapsed() {
|
|
205
|
+
this.collapsed = !this.collapsed;
|
|
128
206
|
}
|
|
129
207
|
}
|
|
130
208
|
|
|
@@ -4,10 +4,12 @@ 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
|
-
|
|
11
|
+
[part='link'] {
|
|
12
|
+
width: 100%;
|
|
11
13
|
gap: var(--lumo-space-xs);
|
|
12
14
|
padding: var(--lumo-space-s);
|
|
13
15
|
padding-inline-start: calc(var(--lumo-space-s) + var(--_child-indent, 0px));
|
|
@@ -17,74 +19,84 @@ export const sideNavItemStyles = css`
|
|
|
17
19
|
min-height: var(--lumo-icon-size-m);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
[part='link'][href] {
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:host([disabled]) [part='link'] {
|
|
27
|
+
color: var(--lumo-disabled-text-color);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
[part='toggle-button'] {
|
|
23
31
|
margin-inline-end: calc(var(--lumo-space-xs) * -1);
|
|
24
|
-
padding: 0;
|
|
25
|
-
background: transparent;
|
|
26
|
-
font: inherit;
|
|
27
|
-
color: var(--lumo-tertiary-text-color);
|
|
28
32
|
width: var(--lumo-size-s);
|
|
29
33
|
height: var(--lumo-size-s);
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:host([has-children]) [part='content'] {
|
|
37
|
+
padding-inline-end: var(--lumo-space-s);
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
@media (any-hover: hover) {
|
|
35
|
-
|
|
41
|
+
[part='link']:hover {
|
|
36
42
|
color: var(--lumo-header-text-color);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
button:hover {
|
|
45
|
+
[part='toggle-button']:hover {
|
|
40
46
|
color: var(--lumo-body-text-color);
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
[part='link']:active:focus {
|
|
45
51
|
background-color: var(--lumo-contrast-5pct);
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
button::before {
|
|
49
|
-
font-family: lumo-icons;
|
|
54
|
+
[part='toggle-button']::before {
|
|
50
55
|
content: var(--lumo-icons-dropdown);
|
|
51
|
-
font-size: 1.5em;
|
|
52
|
-
line-height: var(--lumo-size-s);
|
|
53
|
-
display: inline-block;
|
|
54
56
|
transform: rotate(-90deg);
|
|
55
57
|
transition: transform 140ms;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
:host([
|
|
60
|
+
:host([dir='rtl']) [part='toggle-button']::before {
|
|
61
|
+
transform: rotate(90deg);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:host([expanded]) [part='toggle-button']::before {
|
|
59
65
|
transform: none;
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
@supports selector(:focus-visible) {
|
|
63
|
-
|
|
64
|
-
button {
|
|
69
|
+
[part='link'],
|
|
70
|
+
[part='toggle-button'] {
|
|
65
71
|
outline: none;
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
button:focus-visible {
|
|
74
|
+
[part='link']:focus-visible,
|
|
75
|
+
[part='toggle-button']:focus-visible {
|
|
70
76
|
border-radius: var(--lumo-border-radius-m);
|
|
71
77
|
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct);
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
[part='link']:active {
|
|
76
82
|
color: var(--lumo-header-text-color);
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
slot:not([name]) {
|
|
80
|
-
margin: 0 var(--lumo-space-
|
|
86
|
+
margin: 0 var(--lumo-space-s);
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
slot[name='prefix']::slotted(:is(vaadin-icon, [class*='icon'])) {
|
|
90
|
+
padding: 0.1em;
|
|
91
|
+
flex-shrink: 0;
|
|
84
92
|
color: var(--lumo-contrast-60pct);
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
:host([
|
|
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'])) {
|
|
88
100
|
color: inherit;
|
|
89
101
|
}
|
|
90
102
|
|
|
@@ -96,10 +108,10 @@ export const sideNavItemStyles = css`
|
|
|
96
108
|
--_child-indent-2: var(--_child-indent);
|
|
97
109
|
}
|
|
98
110
|
|
|
99
|
-
:host([
|
|
111
|
+
:host([current]) [part='link'] {
|
|
100
112
|
color: var(--lumo-primary-text-color);
|
|
101
113
|
background-color: var(--lumo-primary-color-10pct);
|
|
102
114
|
}
|
|
103
115
|
`;
|
|
104
116
|
|
|
105
|
-
registerStyles('vaadin-side-nav-item', sideNavItemStyles, { moduleId: 'lumo-side-nav-item' });
|
|
117
|
+
registerStyles('vaadin-side-nav-item', [fieldButton, sideNavItemStyles], { moduleId: 'lumo-side-nav-item' });
|
|
@@ -16,49 +16,63 @@ export const sideNavStyles = css`
|
|
|
16
16
|
-webkit-tap-highlight-color: transparent;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
[part='label'] {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
width: 100%;
|
|
23
|
+
outline: none;
|
|
24
|
+
box-sizing: border-box;
|
|
21
25
|
border-radius: var(--lumo-border-radius-m);
|
|
26
|
+
font-family: var(--lumo-font-family);
|
|
27
|
+
font-size: var(--lumo-font-size-s);
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
line-height: var(--lumo-line-height-xs);
|
|
22
30
|
}
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
font-size: var(--lumo-font-size-s);
|
|
32
|
+
[part='label'] ::slotted([slot='label']) {
|
|
26
33
|
color: var(--lumo-secondary-text-color);
|
|
27
34
|
margin: var(--lumo-space-s);
|
|
28
|
-
border-radius: inherit;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
:host([focus-ring]) [part='label'] {
|
|
38
|
+
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
[part='toggle-button'] {
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
35
45
|
width: var(--lumo-size-s);
|
|
36
46
|
height: var(--lumo-size-s);
|
|
37
|
-
|
|
38
|
-
margin:
|
|
47
|
+
margin-inline-start: auto;
|
|
48
|
+
margin-inline-end: var(--lumo-space-xs);
|
|
49
|
+
font-size: var(--lumo-icon-size-m);
|
|
50
|
+
line-height: 1;
|
|
51
|
+
color: var(--lumo-contrast-60pct);
|
|
52
|
+
font-family: 'lumo-icons';
|
|
53
|
+
cursor: var(--lumo-clickable-cursor);
|
|
39
54
|
}
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
content: var(--lumo-icons-
|
|
56
|
+
[part='toggle-button']::before {
|
|
57
|
+
content: var(--lumo-icons-angle-right);
|
|
58
|
+
transition: transform 140ms;
|
|
43
59
|
}
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
color: var(--lumo-body-text-color);
|
|
48
|
-
}
|
|
61
|
+
:host(:not([collapsible])) [part='toggle-button'] {
|
|
62
|
+
display: none !important;
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
:host([collapsed])
|
|
52
|
-
transform: rotate(
|
|
65
|
+
:host(:not([collapsed])) [part='toggle-button']::before {
|
|
66
|
+
transform: rotate(90deg);
|
|
53
67
|
}
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
69
|
+
:host([collapsed][dir='rtl']) [part='toggle-button']::before {
|
|
70
|
+
transform: rotate(180deg);
|
|
71
|
+
}
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
@media (any-hover: hover) {
|
|
74
|
+
[part='label']:hover [part='toggle-button'] {
|
|
75
|
+
color: var(--lumo-body-text-color);
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
`;
|
|
@@ -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,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' });
|
|
@@ -1,7 +1,8 @@
|
|
|
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
|
+
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';
|