material-inspired-component-library 1.2.2 → 2.0.0
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 +18 -0
- package/components/badge/README.md +65 -0
- package/components/badge/index.scss +68 -0
- package/components/button/README.md +1 -1
- package/components/button/index.scss +60 -89
- package/components/button/index.ts +5 -0
- package/components/card/index.scss +29 -30
- package/components/checkbox/index.scss +1 -6
- package/components/dialog/index.scss +11 -7
- package/components/iconbutton/README.md +1 -1
- package/components/iconbutton/index.scss +46 -80
- package/components/iconbutton/index.ts +5 -0
- package/components/list/index.scss +39 -30
- package/components/list/index.ts +10 -9
- package/components/menu/README.md +67 -4
- package/components/menu/index.scss +29 -29
- package/components/menu/index.ts +47 -16
- package/components/navigationrail/README.md +150 -0
- package/components/navigationrail/index.scss +468 -0
- package/components/{checkbox → navigationrail}/index.ts +12 -7
- package/components/radio/index.scss +22 -12
- package/components/select/index.scss +5 -11
- package/components/textfield/index.scss +8 -2
- package/dist/badge.css +1 -0
- package/dist/badge.js +1 -0
- package/dist/bottomsheet.css +1 -1
- package/dist/button.css +1 -1
- package/dist/card.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/components/menu/index.d.ts +0 -11
- package/dist/components/navigationrail/index.d.ts +5 -0
- package/dist/dialog.css +1 -1
- package/dist/iconbutton.css +1 -1
- package/dist/list.css +1 -1
- package/dist/menu.css +1 -1
- package/dist/micl.css +1 -1
- package/dist/micl.js +1 -1
- package/dist/navigationrail.css +1 -0
- package/dist/navigationrail.js +1 -0
- package/dist/radio.css +1 -1
- package/dist/select.css +1 -1
- package/dist/slider.css +1 -1
- package/dist/switch.css +1 -1
- package/dist/textfield.css +1 -1
- package/docs/button.html +5 -5
- package/docs/docs.css +2 -1
- package/docs/docs.js +2 -2
- package/docs/index.html +35 -2
- package/docs/menu.html +183 -3
- package/docs/micl.css +1 -1
- package/docs/micl.js +1 -1
- package/docs/navigationrail.html +81 -0
- package/micl.ts +20 -25
- package/package.json +10 -7
- package/styles/statelayer.scss +14 -0
- package/styles.scss +18 -1
- package/webpack.config.js +37 -0
- package/dist/components/checkbox/index.d.ts +0 -5
- package/styles/ripple.scss +0 -50
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Navigation rail
|
|
2
|
+
This component implements the the [Material Design 3 Expressive Navigation rail](https://m3.material.io/components/navigation-rail/overview) design.
|
|
3
|
+
|
|
4
|
+
## Basic Usage
|
|
5
|
+
|
|
6
|
+
### HTML
|
|
7
|
+
To create a simple navigation rail, use a `<div>` element with the `micl-navigationrail` class. Inside, use an `input type="radio"` group to create the selectable navigation items. The `input` elements must share the same `name` attribute to ensure that only one item can be selected at a time. The `label` elements are associated with their respective inputs using the `for` attribute.
|
|
8
|
+
|
|
9
|
+
```HTML
|
|
10
|
+
<div id="mynavigationrail" class="micl-navigationrail">
|
|
11
|
+
<div class="micl-navigationrail__content">
|
|
12
|
+
<input type="radio" id="item1" name="navitem" value="email_inbox" checked>
|
|
13
|
+
<label for="item1" class="micl-navigationrail__item" tabindex="0">
|
|
14
|
+
<span class="micl-navigationrail__icon material-symbols-outlined" aria-hidden="true">inbox</span>
|
|
15
|
+
<span class="micl-navigationrail__text">Inbox</span>
|
|
16
|
+
</label>
|
|
17
|
+
<input type="radio" id="item2" name="navitem" value="email_outbox">
|
|
18
|
+
<label for="item2" class="micl-navigationrail__item" tabindex="0">
|
|
19
|
+
<span class="micl-navigationrail__icon material-symbols-outlined" aria-hidden="true">outbox</span>
|
|
20
|
+
<span class="micl-navigationrail__text">Outbox</span>
|
|
21
|
+
</label>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### CSS
|
|
27
|
+
Import the navigation rail styles into your project:
|
|
28
|
+
|
|
29
|
+
```CSS
|
|
30
|
+
@use "material-inspired-component-library/dist/navigationrail";
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### JavaScript
|
|
34
|
+
This component requires JavaScript to support keyboard navigation. The library will automatically initialize new components as they're added to the DOM.
|
|
35
|
+
|
|
36
|
+
```JavaScript
|
|
37
|
+
import micl from "material-inspired-component-library/dist/micl";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Demo
|
|
41
|
+
A live example of the [Navigation rail component](https://henkpb.github.io/micl/navigationrail.html) is available for you to interact with.
|
|
42
|
+
|
|
43
|
+
## Variants
|
|
44
|
+
The basic example creates a **collapsed** navigation rail. Add a menu button to allow the user to toggle between a **collapsed** and an **expanded** view.
|
|
45
|
+
|
|
46
|
+
```HTML
|
|
47
|
+
<div id="mynavigationrail" class="micl-navigationrail">
|
|
48
|
+
<div class="micl-navigationrail__headline">
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
class="micl-iconbutton-standard-s micl-button--toggle material-symbols-outlined"
|
|
52
|
+
data-miclalt="menu_open"
|
|
53
|
+
aria-label="Toggle navigation rail"
|
|
54
|
+
>menu</button>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="micl-navigationrail__content">
|
|
57
|
+
...
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
When the user clicks the menu button, the navigation rail is expanded and the toggle button is given the `micl-button--selected` class and the `micl-button--toggled` class that indicates that the toggle button has been clicked at least once.
|
|
63
|
+
|
|
64
|
+
### Popover expanded navigation rail
|
|
65
|
+
|
|
66
|
+
Add the `popover` attribute to the navigation rail, and the `popovertarget` attribute to the menu button. The value of the `popovertarget` attribute must be the `id` of the navigation rail.
|
|
67
|
+
|
|
68
|
+
```HTML
|
|
69
|
+
<div id="mynavigationrail" class="micl-navigationrail" popover="manual">
|
|
70
|
+
<div class="micl-navigationrail__headline">
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
class="micl-iconbutton-standard-s micl-button--toggle material-symbols-outlined"
|
|
74
|
+
popovertarget="mynavigationrail"
|
|
75
|
+
data-miclalt="menu_open"
|
|
76
|
+
aria-label="Toggle navigation rail"
|
|
77
|
+
>menu</button>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="micl-navigationrail__content">
|
|
80
|
+
...
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
[!WARNING]
|
|
86
|
+
The **popover** navigation rail component adds CSS rules to the `<body>` element to properly resize the main content area when the navigation rail is collapsed. Overriding these rules may cause the component to behave unexpectedly. The rules that are applied are:
|
|
87
|
+
|
|
88
|
+
```CSS
|
|
89
|
+
margin-inline-start: var(--md-sys-navigationrail-collapsed-width);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Modal navigation rail
|
|
93
|
+
|
|
94
|
+
A **modal** navigation rail is hidden until the user clicks a menu button. When shown, the **expanded** navigation rail is displayed on top of other page content. Use a `<dialog>` element instead of a `<div>`.
|
|
95
|
+
|
|
96
|
+
```HTML
|
|
97
|
+
<dialog id="mynavigationrail" class="micl-navigationrail" closedby="closerequest">
|
|
98
|
+
<div class="micl-navigationrail__headline">
|
|
99
|
+
<button
|
|
100
|
+
type="button"
|
|
101
|
+
class="micl-iconbutton-standard-s micl-button--toggle material-symbols-outlined"
|
|
102
|
+
popovertarget="mynavigationrail"
|
|
103
|
+
data-miclalt="menu_open"
|
|
104
|
+
aria-label="Toggle navigation rail"
|
|
105
|
+
>menu</button>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="micl-navigationrail__content">
|
|
108
|
+
...
|
|
109
|
+
</div>
|
|
110
|
+
</dialog>
|
|
111
|
+
|
|
112
|
+
<button
|
|
113
|
+
type="button"
|
|
114
|
+
class="micl-iconbutton-standard-s micl-button--toggle material-symbols-outlined"
|
|
115
|
+
popovertarget="mynavigationrail"
|
|
116
|
+
aria-label="Toggle navigation rail"
|
|
117
|
+
>menu</button>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The button inside the navigation rail is used to hide the navigation rail, while the button outside is responsible for opening it.
|
|
121
|
+
|
|
122
|
+
## Customizations
|
|
123
|
+
You can customize the appearance of the Navigation rail component by overriding its global CSS variables. These variables are declared on the `:root` pseudo-class and can be changed on any appropriate parent element to affect its child navigation rails.
|
|
124
|
+
|
|
125
|
+
| Variable name | Default Value | Description |
|
|
126
|
+
| ------------- | ------------- | ----------- |
|
|
127
|
+
| --md-sys-navigationrail-collapsed-width | 96px | The width of the collapsed navigation rail |
|
|
128
|
+
| --md-sys-navigationrail-expanded-maxwidth | 360px | The largest allowed width of the expanded navigation rail |
|
|
129
|
+
| --md-sys-navigationrail-expanded-minwidth | 220px | The smallest allowed width of the expanded navigation rail |
|
|
130
|
+
|
|
131
|
+
**Example: Changing the width of the collapsed navigation rail**
|
|
132
|
+
|
|
133
|
+
```HTML
|
|
134
|
+
<div style="--md-sys-navigationrail-collapsed-width:80px">
|
|
135
|
+
<div id="mynavigationrail" class="micl-navigationrail">
|
|
136
|
+
...
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
To add a vertical divider of the to the navigation rail, assign one to the following CSS variable:
|
|
142
|
+
|
|
143
|
+
```CSS
|
|
144
|
+
#mynavigationrail {
|
|
145
|
+
--md-sys-divider-thickness: 1;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Compatibility
|
|
150
|
+
This component uses the Popover API, which might not be supported in all browsers. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API#api.htmlelement.popover) for details.
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright © 2025 Hermana AS
|
|
3
|
+
//
|
|
4
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
// in the Software without restriction, including without limitation the rights
|
|
7
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
// furnished to do so, subject to the following conditions:
|
|
10
|
+
//
|
|
11
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
// copies or substantial portions of the Software.
|
|
13
|
+
//
|
|
14
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
// SOFTWARE.
|
|
21
|
+
|
|
22
|
+
@use '../../styles/elevation';
|
|
23
|
+
@use '../../styles/motion';
|
|
24
|
+
@use '../../styles/shapes';
|
|
25
|
+
@use '../../styles/statelayer';
|
|
26
|
+
@use '../../styles/typography';
|
|
27
|
+
|
|
28
|
+
:root {
|
|
29
|
+
--md-sys-navigationrail-collapsed-width: 96px;
|
|
30
|
+
--md-sys-navigationrail-expanded-maxwidth: 360px;
|
|
31
|
+
--md-sys-navigationrail-expanded-minwidth: 220px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.micl-navigationrail {
|
|
35
|
+
--md-sys-navigationrail-spring-buffer: 200px;
|
|
36
|
+
--md-sys-navigationrail-header-space: 40px;
|
|
37
|
+
--md-sys-navigationrail-top-space: 44px;
|
|
38
|
+
--md-sys-navigationrail-item-space: 6px;
|
|
39
|
+
--md-sys-navigationrail-item-height: 56px;
|
|
40
|
+
--md-sys-divider-thickness: 0px;
|
|
41
|
+
--md-sys-navigationrail-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
|
|
42
|
+
--md-sys-navigationrail-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
|
|
43
|
+
--md-sys-navigationrail-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
|
|
44
|
+
--md-sys-navigationrail-morph-duration: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
|
|
45
|
+
--md-sys-navigationrail-morph-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
|
|
46
|
+
|
|
47
|
+
box-sizing: border-box;
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
align-items: flex-start;
|
|
51
|
+
min-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
52
|
+
max-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
53
|
+
block-size: 100vh;
|
|
54
|
+
min-block-size: 100%;
|
|
55
|
+
margin-block: 0;
|
|
56
|
+
margin-inline: 0 auto;
|
|
57
|
+
padding-block: var(--md-sys-navigationrail-top-space) 0;
|
|
58
|
+
padding-inline: 0;
|
|
59
|
+
background-color: var(--md-sys-color-surface);
|
|
60
|
+
border: none;
|
|
61
|
+
box-shadow: var(--md-sys-elevation-level0);
|
|
62
|
+
opacity: 100%;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
interpolate-size: allow-keywords;
|
|
65
|
+
|
|
66
|
+
&> .micl-navigationrail__headline {
|
|
67
|
+
padding-inline-start: 24px;
|
|
68
|
+
}
|
|
69
|
+
&> .micl-navigationrail__content {
|
|
70
|
+
box-sizing: border-box;
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
flex: 1 1 auto;
|
|
74
|
+
align-items: flex-start;
|
|
75
|
+
row-gap: var(--md-sys-navigationrail-item-space);
|
|
76
|
+
inline-size: 100%;
|
|
77
|
+
padding-block: var(--md-sys-navigationrail-header-space) 0;
|
|
78
|
+
padding-inline: 20px 0;
|
|
79
|
+
overflow: hidden auto;
|
|
80
|
+
transition: row-gap var(--md-sys-navigationrail-morph-duration-reverse) linear;
|
|
81
|
+
|
|
82
|
+
&> input[type=radio] {
|
|
83
|
+
appearance: none;
|
|
84
|
+
display: none;
|
|
85
|
+
margin: 0;
|
|
86
|
+
}
|
|
87
|
+
&> label.micl-navigationrail__item {
|
|
88
|
+
--micl-ripple: 1;
|
|
89
|
+
--statelayer-color: var(--md-sys-color-on-secondary-container);
|
|
90
|
+
|
|
91
|
+
box-sizing: border-box;
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
align-items: center;
|
|
95
|
+
block-size: var(--md-sys-navigationrail-item-height);
|
|
96
|
+
inline-size: var(--md-sys-navigationrail-item-height);
|
|
97
|
+
row-gap: 4px;
|
|
98
|
+
padding-block: 12px;
|
|
99
|
+
border-radius: calc(var(--md-sys-navigationrail-item-height) / 2);
|
|
100
|
+
outline: none;
|
|
101
|
+
background-color: transparent;
|
|
102
|
+
background-image:
|
|
103
|
+
radial-gradient(circle at var(--micl-x, center) var(--micl-y, center), transparent 0%, rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)) 10%, transparent 10%),
|
|
104
|
+
linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
|
|
105
|
+
background-repeat: no-repeat;
|
|
106
|
+
background-size: 10000%, 100%;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
transition:
|
|
109
|
+
inline-size calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
110
|
+
background-color calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
111
|
+
background-size 3000ms,
|
|
112
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
113
|
+
|
|
114
|
+
&> .micl-navigationrail__icon {
|
|
115
|
+
--micl-ripple: 1;
|
|
116
|
+
|
|
117
|
+
font-size: 24px;
|
|
118
|
+
inline-size: 24px;
|
|
119
|
+
margin: 0;
|
|
120
|
+
padding-block: 4px;
|
|
121
|
+
padding-inline: 16px;
|
|
122
|
+
border-radius: 16px;
|
|
123
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
124
|
+
background-color: transparent;
|
|
125
|
+
background-image:
|
|
126
|
+
radial-gradient(circle at var(--micl-x, center) var(--micl-y, center), transparent 0%, rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)) 10%, transparent 10%),
|
|
127
|
+
linear-gradient(rgb(from var(--statelayer-color) r g b / var(--statelayer-opacity)));
|
|
128
|
+
background-repeat: no-repeat;
|
|
129
|
+
background-size: 10000%, 100%;
|
|
130
|
+
font-variation-settings: 'FILL' 0;
|
|
131
|
+
transition:
|
|
132
|
+
background-size 3000ms,
|
|
133
|
+
background-color var(--md-sys-navigationrail-morph-duration-reverse) linear,
|
|
134
|
+
font-variation-settings var(--md-sys-navigationrail-morph-duration-reverse) linear,
|
|
135
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
136
|
+
}
|
|
137
|
+
&> .micl-navigationrail__text {
|
|
138
|
+
@include typography.label-medium;
|
|
139
|
+
|
|
140
|
+
min-block-size: var(--md-sys-typescale-label-medium-line-height);
|
|
141
|
+
margin-block-start: 0;
|
|
142
|
+
margin-inline-start: 0px;
|
|
143
|
+
padding-inline-end: 0px;
|
|
144
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
145
|
+
opacity: 100%;
|
|
146
|
+
overflow: hidden;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
&> input[type=radio]:checked + label.micl-navigationrail__item {
|
|
150
|
+
&> .micl-navigationrail__icon {
|
|
151
|
+
background-color: var(--md-sys-color-secondary-container);
|
|
152
|
+
color: var(--md-sys-color-on-secondary-container);
|
|
153
|
+
font-variation-settings: 'FILL' 1;
|
|
154
|
+
transition:
|
|
155
|
+
background-size 3000ms,
|
|
156
|
+
background-color var(--md-sys-navigationrail-morph-duration) linear,
|
|
157
|
+
font-variation-settings var(--md-sys-navigationrail-morph-duration) linear,
|
|
158
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
159
|
+
}
|
|
160
|
+
&> .micl-navigationrail__text {
|
|
161
|
+
color: var(--md-sys-color-secondary);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
dialog.micl-navigationrail,
|
|
167
|
+
div.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle.micl-button--selected) {
|
|
168
|
+
max-inline-size: var(--md-sys-navigationrail-expanded-maxwidth);
|
|
169
|
+
min-inline-size: var(--md-sys-navigationrail-expanded-minwidth);
|
|
170
|
+
|
|
171
|
+
&> .micl-navigationrail__content {
|
|
172
|
+
row-gap: 0px;
|
|
173
|
+
|
|
174
|
+
&> label.micl-navigationrail__item {
|
|
175
|
+
position: relative;
|
|
176
|
+
flex-direction: row;
|
|
177
|
+
inline-size: fit-content;
|
|
178
|
+
|
|
179
|
+
&::before {
|
|
180
|
+
content: "";
|
|
181
|
+
position: absolute;
|
|
182
|
+
inset: 0px;
|
|
183
|
+
inset-inline-end: calc(-1 * (var(--md-sys-navigationrail-expanded-maxwidth) - 20px - 100%));
|
|
184
|
+
background-color: transparent;
|
|
185
|
+
}
|
|
186
|
+
&:hover {
|
|
187
|
+
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
|
|
188
|
+
}
|
|
189
|
+
&:focus-visible {
|
|
190
|
+
--statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity);
|
|
191
|
+
}
|
|
192
|
+
&:active {
|
|
193
|
+
background-size: 0%, 100%;
|
|
194
|
+
transition: background-size 0ms;
|
|
195
|
+
--statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity);
|
|
196
|
+
}
|
|
197
|
+
&> .micl-navigationrail__text {
|
|
198
|
+
@include typography.label-large;
|
|
199
|
+
|
|
200
|
+
margin-inline-start: -8px;
|
|
201
|
+
padding-inline-end: 16px;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
&> input[type=radio]:checked + label.micl-navigationrail__item {
|
|
205
|
+
background-color: var(--md-sys-color-secondary-container);
|
|
206
|
+
|
|
207
|
+
&> .micl-navigationrail__icon {
|
|
208
|
+
background-color: transparent;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
div.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle.micl-button--selected) {
|
|
214
|
+
&> .micl-navigationrail__content {
|
|
215
|
+
transition: row-gap var(--md-sys-navigationrail-morph-duration) linear;
|
|
216
|
+
|
|
217
|
+
&> label.micl-navigationrail__item {
|
|
218
|
+
transition:
|
|
219
|
+
inline-size calc(var(--md-sys-navigationrail-morph-duration) / 2) calc(var(--md-sys-navigationrail-morph-duration) / 2) linear,
|
|
220
|
+
background-color calc(var(--md-sys-navigationrail-morph-duration) / 2) calc(var(--md-sys-navigationrail-morph-duration) / 2) linear,
|
|
221
|
+
background-size 3000ms,
|
|
222
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
223
|
+
}
|
|
224
|
+
&> input[type=radio]:checked + label.micl-navigationrail__item {
|
|
225
|
+
&> .micl-navigationrail__icon {
|
|
226
|
+
transition:
|
|
227
|
+
background-size 3000ms,
|
|
228
|
+
background-color calc(var(--md-sys-navigationrail-morph-duration) / 2) linear,
|
|
229
|
+
font-variation-settings calc(var(--md-sys-navigationrail-morph-duration) / 2) linear,
|
|
230
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
div.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle.micl-button--toggled.micl-button--selected) {
|
|
236
|
+
animation: var(--md-sys-navigationrail-morph-duration) linear forwards navigationrail-to-expanded;
|
|
237
|
+
|
|
238
|
+
&> .micl-navigationrail__content > label.micl-navigationrail__item {
|
|
239
|
+
animation: calc(var(--md-sys-navigationrail-morph-duration) / 2) linear forwards navigationrail-item-to-expanded;
|
|
240
|
+
|
|
241
|
+
&> .micl-navigationrail__text {
|
|
242
|
+
animation: var(--md-sys-navigationrail-morph-duration) linear forwards navigationrail-text-to-expanded;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
div.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle.micl-button--toggled:not(.micl-button--selected)) {
|
|
247
|
+
animation: var(--md-sys-navigationrail-morph-duration-reverse) linear forwards navigationrail-to-collapsed;
|
|
248
|
+
|
|
249
|
+
&> .micl-navigationrail__content {
|
|
250
|
+
&> label.micl-navigationrail__item {
|
|
251
|
+
animation: calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear forwards navigationrail-item-to-collapsed;
|
|
252
|
+
|
|
253
|
+
&> .micl-navigationrail__text {
|
|
254
|
+
animation: var(--md-sys-navigationrail-morph-duration-reverse) linear forwards navigationrail-text-to-collapsed;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
&> input[type=radio]:checked + label.micl-navigationrail__item {
|
|
258
|
+
&> .micl-navigationrail__icon {
|
|
259
|
+
transition:
|
|
260
|
+
background-size 3000ms,
|
|
261
|
+
background-color calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
262
|
+
font-variation-settings calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
263
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
div.micl-navigationrail:has(> .micl-navigationrail__headline .micl-button--toggle:not(.micl-button--selected)) {
|
|
269
|
+
&> .micl-navigationrail__content > label.micl-navigationrail__item {
|
|
270
|
+
&:hover {
|
|
271
|
+
&> .micl-navigationrail__icon {
|
|
272
|
+
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
&:focus-visible {
|
|
276
|
+
&> .micl-navigationrail__icon {
|
|
277
|
+
--statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
&:active {
|
|
281
|
+
&> .micl-navigationrail__icon {
|
|
282
|
+
--statelayer-opacity: var(--md-sys-state-pressed-state-layer-opacity);
|
|
283
|
+
|
|
284
|
+
background-size: 0%, 100%;
|
|
285
|
+
transition:
|
|
286
|
+
background-size 0ms,
|
|
287
|
+
background-color calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
288
|
+
font-variation-settings calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) calc(var(--md-sys-navigationrail-morph-duration-reverse) / 2) linear,
|
|
289
|
+
--statelayer-opacity var(--md-sys-navigationrail-motion-duration) linear;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
dialog.micl-navigationrail {
|
|
296
|
+
display: none;
|
|
297
|
+
min-inline-size: calc(var(--md-sys-navigationrail-expanded-minwidth) + var(--md-sys-navigationrail-spring-buffer));
|
|
298
|
+
max-inline-size: calc(var(--md-sys-navigationrail-expanded-maxwidth) + var(--md-sys-navigationrail-spring-buffer));
|
|
299
|
+
margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-expanded-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
|
|
300
|
+
padding-inline: var(--md-sys-navigationrail-spring-buffer) 0;
|
|
301
|
+
opacity: 0%;
|
|
302
|
+
transition:
|
|
303
|
+
opacity var(--md-sys-navigationrail-motion-duration-reverse) linear,
|
|
304
|
+
margin-inline-start var(--md-sys-navigationrail-motion-duration-reverse) var(--md-sys-navigationrail-motion-spatial),
|
|
305
|
+
overlay var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete,
|
|
306
|
+
display var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete;
|
|
307
|
+
|
|
308
|
+
&[open] {
|
|
309
|
+
display: flex;
|
|
310
|
+
margin-inline-start: calc(-1 * var(--md-sys-navigationrail-spring-buffer));
|
|
311
|
+
opacity: 100%;
|
|
312
|
+
|
|
313
|
+
@starting-style {
|
|
314
|
+
margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-expanded-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
|
|
315
|
+
opacity: 0%;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
div.micl-navigationrail {
|
|
320
|
+
position: sticky;
|
|
321
|
+
float: inline-start;
|
|
322
|
+
inset: unset;
|
|
323
|
+
inset-block-start: 0;
|
|
324
|
+
inset-inline-start: 0;
|
|
325
|
+
border-inline-end: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
|
|
326
|
+
}
|
|
327
|
+
div.micl-navigationrail[popover] {
|
|
328
|
+
position: fixed;
|
|
329
|
+
}
|
|
330
|
+
.micl-navigationrail {
|
|
331
|
+
&[open],
|
|
332
|
+
&:popover-open {
|
|
333
|
+
border-start-end-radius: var(--md-sys-shape-corner-large);
|
|
334
|
+
border-end-end-radius: var(--md-sys-shape-corner-large);
|
|
335
|
+
box-shadow: var(--md-sys-elevation-level2);
|
|
336
|
+
background-color: var(--md-sys-color-surface-container);
|
|
337
|
+
transition:
|
|
338
|
+
opacity var(--md-sys-navigationrail-motion-duration) linear,
|
|
339
|
+
margin-inline-start var(--md-sys-navigationrail-motion-duration) var(--md-sys-navigationrail-motion-spatial),
|
|
340
|
+
overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
|
|
341
|
+
display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
|
|
342
|
+
|
|
343
|
+
&::backdrop {
|
|
344
|
+
background-color: rgba(0, 0, 0, 0.2);
|
|
345
|
+
|
|
346
|
+
@starting-style {
|
|
347
|
+
background-color: rgba(0, 0, 0, 0);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
&::backdrop {
|
|
352
|
+
background-color: rgba(0, 0, 0, 0);
|
|
353
|
+
transition:
|
|
354
|
+
background-color var(--md-sys-navigationrail-motion-duration) linear,
|
|
355
|
+
overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
|
|
356
|
+
display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
body:has(div.micl-navigationrail[popover]) {
|
|
360
|
+
margin-inline-start: var(--md-sys-navigationrail-collapsed-width);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
@keyframes navigationrail-to-expanded {
|
|
364
|
+
from {
|
|
365
|
+
max-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
366
|
+
min-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
367
|
+
}
|
|
368
|
+
to {
|
|
369
|
+
max-inline-size: var(--md-sys-navigationrail-expanded-maxwidth);
|
|
370
|
+
min-inline-size: var(--md-sys-navigationrail-expanded-minwidth);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
@keyframes navigationrail-to-collapsed {
|
|
374
|
+
from {
|
|
375
|
+
max-inline-size: var(--md-sys-navigationrail-expanded-maxwidth);
|
|
376
|
+
min-inline-size: var(--md-sys-navigationrail-expanded-minwidth);
|
|
377
|
+
}
|
|
378
|
+
to {
|
|
379
|
+
max-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
380
|
+
min-inline-size: var(--md-sys-navigationrail-collapsed-width);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
@keyframes navigationrail-item-to-expanded {
|
|
384
|
+
0% {
|
|
385
|
+
flex-direction: column;
|
|
386
|
+
}
|
|
387
|
+
99% {
|
|
388
|
+
flex-direction: column;
|
|
389
|
+
}
|
|
390
|
+
100% {
|
|
391
|
+
flex-direction: row;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
@keyframes navigationrail-item-to-collapsed {
|
|
395
|
+
0% {
|
|
396
|
+
flex-direction: row;
|
|
397
|
+
}
|
|
398
|
+
99% {
|
|
399
|
+
flex-direction: row;
|
|
400
|
+
}
|
|
401
|
+
100% {
|
|
402
|
+
flex-direction: column;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
@keyframes navigationrail-text-to-collapsed {
|
|
406
|
+
0% {
|
|
407
|
+
@include typography.label-large;
|
|
408
|
+
margin-block-start: 0;
|
|
409
|
+
margin-inline-start: -8px;
|
|
410
|
+
padding-inline-end: 16px;
|
|
411
|
+
opacity: 100%
|
|
412
|
+
}
|
|
413
|
+
49.9% {
|
|
414
|
+
@include typography.label-large;
|
|
415
|
+
margin-block-start: 0;
|
|
416
|
+
margin-inline-start: -8px;
|
|
417
|
+
padding-inline-end: 16px;
|
|
418
|
+
opacity: 0%;
|
|
419
|
+
}
|
|
420
|
+
50.1% {
|
|
421
|
+
@include typography.label-medium;
|
|
422
|
+
min-block-size: var(--md-sys-typescale-label-medium-line-height);
|
|
423
|
+
margin-block-start: -16px;
|
|
424
|
+
margin-inline-start: 0px;
|
|
425
|
+
padding-inline-end: 0px;
|
|
426
|
+
opacity: 0%;
|
|
427
|
+
}
|
|
428
|
+
100% {
|
|
429
|
+
@include typography.label-medium;
|
|
430
|
+
min-block-size: var(--md-sys-typescale-label-medium-line-height);
|
|
431
|
+
margin-block-start: 0;
|
|
432
|
+
margin-inline-start: 0px;
|
|
433
|
+
padding-inline-end: 0px;
|
|
434
|
+
opacity: 100%;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
@keyframes navigationrail-text-to-expanded {
|
|
438
|
+
0% {
|
|
439
|
+
@include typography.label-medium;
|
|
440
|
+
min-block-size: var(--md-sys-typescale-label-medium-line-height);
|
|
441
|
+
margin-block-start: 0;
|
|
442
|
+
margin-inline-start: 0px;
|
|
443
|
+
padding-inline-end: 0px;
|
|
444
|
+
opacity: 100%;
|
|
445
|
+
}
|
|
446
|
+
49.9% {
|
|
447
|
+
@include typography.label-medium;
|
|
448
|
+
min-block-size: var(--md-sys-typescale-label-medium-line-height);
|
|
449
|
+
margin-block-start: -16px;
|
|
450
|
+
margin-inline-start: 0px;
|
|
451
|
+
padding-inline-end: 0px;
|
|
452
|
+
opacity: 0%;
|
|
453
|
+
}
|
|
454
|
+
50.1% {
|
|
455
|
+
@include typography.label-large;
|
|
456
|
+
margin-block-start: 0px;
|
|
457
|
+
margin-inline-start: -8px;
|
|
458
|
+
padding-inline-end: 16px;
|
|
459
|
+
opacity: 0%;
|
|
460
|
+
}
|
|
461
|
+
100% {
|
|
462
|
+
@include typography.label-large;
|
|
463
|
+
margin-block-start: 0px;
|
|
464
|
+
margin-inline-start: -8px;
|
|
465
|
+
padding-inline-end: 16px;
|
|
466
|
+
opacity: 100%;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
|
-
export const
|
|
22
|
+
export const navigationrailSelector = '.micl-navigationrail__item[for]:not(.micl-navigationrail__item--disabled)';
|
|
23
23
|
|
|
24
24
|
export default (() =>
|
|
25
25
|
{
|
|
@@ -27,19 +27,24 @@ export default (() =>
|
|
|
27
27
|
keydown: (event: Event) =>
|
|
28
28
|
{
|
|
29
29
|
if (
|
|
30
|
-
!(event
|
|
31
|
-
|| !(event instanceof
|
|
32
|
-
|| !
|
|
33
|
-
|| (event.target as HTMLInputElement).disabled
|
|
30
|
+
!(event instanceof KeyboardEvent)
|
|
31
|
+
|| !(event.target instanceof HTMLLabelElement)
|
|
32
|
+
|| !event.target.matches(navigationrailSelector)
|
|
34
33
|
) {
|
|
35
34
|
return;
|
|
36
35
|
}
|
|
36
|
+
const input = document.getElementById(event.target.htmlFor) as HTMLInputElement;
|
|
37
|
+
if (!input) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
37
40
|
|
|
38
41
|
switch (event.key) {
|
|
39
42
|
case 'Enter':
|
|
40
43
|
case ' ':
|
|
41
|
-
event.
|
|
42
|
-
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
if (!input.checked) {
|
|
46
|
+
input.checked = !input.checked;
|
|
47
|
+
}
|
|
43
48
|
break;
|
|
44
49
|
default:
|
|
45
50
|
}
|