material-inspired-component-library 1.2.1 → 1.3.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.
Files changed (53) hide show
  1. package/README.md +12 -2
  2. package/components/bottomsheet/index.scss +18 -16
  3. package/components/button/README.md +1 -1
  4. package/components/button/index.scss +57 -80
  5. package/components/card/index.scss +33 -31
  6. package/components/checkbox/index.scss +5 -9
  7. package/components/dialog/index.scss +38 -29
  8. package/components/iconbutton/README.md +1 -1
  9. package/components/iconbutton/index.scss +51 -81
  10. package/components/list/index.scss +45 -33
  11. package/components/list/index.ts +10 -9
  12. package/components/menu/README.md +67 -4
  13. package/components/menu/index.scss +43 -39
  14. package/components/menu/index.ts +47 -16
  15. package/components/navigationrail/README.md +99 -0
  16. package/components/navigationrail/index.scss +157 -0
  17. package/components/radio/index.scss +28 -15
  18. package/components/select/index.scss +4 -12
  19. package/components/sidesheet/index.scss +21 -19
  20. package/components/switch/index.scss +11 -8
  21. package/components/textfield/index.scss +16 -7
  22. package/dist/bottomsheet.css +1 -1
  23. package/dist/button.css +1 -1
  24. package/dist/card.css +1 -1
  25. package/dist/checkbox.css +1 -1
  26. package/dist/components/menu/index.d.ts +0 -11
  27. package/dist/dialog.css +1 -1
  28. package/dist/iconbutton.css +1 -1
  29. package/dist/list.css +1 -1
  30. package/dist/menu.css +1 -1
  31. package/dist/micl.css +1 -1
  32. package/dist/micl.js +1 -1
  33. package/dist/navigationrail.css +1 -0
  34. package/dist/navigationrail.js +1 -0
  35. package/dist/radio.css +1 -1
  36. package/dist/select.css +1 -1
  37. package/dist/sidesheet.css +1 -1
  38. package/dist/slider.css +1 -1
  39. package/dist/switch.css +1 -1
  40. package/dist/textfield.css +1 -1
  41. package/docs/dialog.html +4 -4
  42. package/docs/docs.js +2 -2
  43. package/docs/index.html +3 -1
  44. package/docs/menu.html +183 -3
  45. package/docs/micl.css +1 -1
  46. package/docs/micl.js +1 -1
  47. package/docs/navigationrail.html +75 -0
  48. package/micl.ts +10 -8
  49. package/package.json +7 -7
  50. package/styles/statelayer.scss +14 -0
  51. package/styles.scss +1 -1
  52. package/webpack.config.js +37 -0
  53. package/styles/ripple.scss +0 -50
@@ -4,7 +4,7 @@ This component implements the [Material Design 3 Expressive Menu](https://m3.mat
4
4
  ## Basic Usage
5
5
 
6
6
  ### HTML
7
- The Menu component is an extension of the [List component](../list/README.md). It consists of a `<nav>` element with the `micl-menu` class, which acts as the container for a `<ul>` with the `micl-list` class. The menu can be opened and closed using a control element with the `popovertarget` attribute.
7
+ The Menu component is an extension of the [List component](../list/README.md). It consists of a `<nav>` element with the `micl-menu` class, which acts as the container for a `<ul>` with the `micl-list` class. The menu can be opened and closed using a control element with the `popovertarget` attribute, where the value of the attribute matches the `id` of the menu's `<nav>` element.
8
8
 
9
9
  ```HTML
10
10
  <nav id="mymenu" class="micl-menu" popover>
@@ -17,7 +17,7 @@ The Menu component is an extension of the [List component](../list/README.md). I
17
17
  </ul>
18
18
  </nav>
19
19
 
20
- <button type="button" popovertarget="mymenu">Open Basic Menu</button>
20
+ <button type="button" popovertarget="mymenu">Open Menu</button>
21
21
  ```
22
22
 
23
23
  ### CSS
@@ -68,17 +68,18 @@ Since the Menu component is based on the **List component**, all of its list ite
68
68
  ```
69
69
 
70
70
  **Example: A menu with a link**
71
+
71
72
  To make a menu item function as a link, wrap its content in an `<a>` tag and set the `tabindex` to `-1`. This ensures the link is clickable but does not interfere with menu navigation.
72
73
 
73
74
  ```HTML
74
75
  <nav id="mymenu" class="micl-menu" popover>
75
76
  <ul class="micl-list">
76
- <li class="micl-list-item-two micl-list-item__divider">
77
+ <li class="micl-list-item-two" tabindex="0">
77
78
  <a href="https://www.nytimes.com" tabindex="-1">
78
79
  <span class="micl-list-item__icon material-symbols-outlined" aria-hidden="true">newspaper</span>
79
80
  <span class="micl-list-item__text">
80
81
  <span class="micl-list-item__headline">The New York Times</span>
81
- <span class="micl-list-item__supporting-text">Clicking this item opens the front page of The New York Times</span>
82
+ <span class="micl-list-item__supporting-text">Open the front page of The New York Times</span>
82
83
  </span>
83
84
  </a>
84
85
  </li>
@@ -86,9 +87,71 @@ To make a menu item function as a link, wrap its content in an `<a>` tag and set
86
87
  </nav>
87
88
  ```
88
89
 
90
+ **Example: A menu with a submenu**
91
+
92
+ A menu item may trigger opening a submenu when invoked by a button. Wrap the menu item content in a `<button>` tag, set its `tabindex` to `-1` and add the `popovertarget` attribute that points to the submenu. The button acts then as the control element for the submenu.
93
+
94
+ ```HTML
95
+ <nav id="mymenu" class="micl-menu" popover>
96
+ <ul class="micl-list">
97
+ <li class="micl-list-item-one" tabindex="0">
98
+ <button popovertarget="mysubmenu" tabindex="-1">
99
+ <span class="micl-list-item__text">
100
+ <span class="micl-list-item__headline">Item 1</span>
101
+ </span>
102
+ <span class="micl-list-item__icon material-symbols-outlined">arrow_right</span>
103
+ </button>
104
+ <nav id="mysubmenu" class="micl-menu" popover>
105
+ <ul class="micl-list">
106
+ <li class="micl-list-item-one" tabindex="0">
107
+ <span class="micl-list-item__text">
108
+ <span class="micl-list-item__headline">Item 1-1</span>
109
+ </span>
110
+ </li>
111
+ <li class="micl-list-item-one" tabindex="0">
112
+ <span class="micl-list-item__text">
113
+ <span class="micl-list-item__headline">Item 1-2</span>
114
+ </span>
115
+ </li>
116
+ </ul>
117
+ </nav>
118
+ </li>
119
+ <li class="micl-list-item-one" tabindex="0">
120
+ <span class="micl-list-item__text">
121
+ <span class="micl-list-item__headline">Item 2</span>
122
+ </span>
123
+ </li>
124
+ </ul>
125
+ </nav>
126
+ ```
127
+
89
128
  Adding the `micl-list-item--disabled` class to a menu item causes the item to be displayed in a disabled state.
90
129
 
91
130
  Add the `micl-list-item__divider` class to a menu item to create a divider between the item and the previous menu item.
92
131
 
132
+ ## Customizations
133
+ You can customize the appearance of the Menu 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 menus.
134
+
135
+ | Variable name | Default Value | Description |
136
+ | ------------- | ----- | ----------- |
137
+ | --md-sys-menu-width-max | 280px | The maximum width allowed for a menu |
138
+ | --md-sys-menu-width-min | 112px | The minimum allowed width for a menu |
139
+
140
+ **Example: Changing the maximum width**
141
+
142
+ ```HTML
143
+ <div style="--md-sys-menu-width-max:320px">
144
+ <nav id="mymenu" class="micl-menu" popover>
145
+ <ul class="micl-list">
146
+ <li class="micl-list-item-one" tabindex="0">
147
+ <span class="micl-list-item__text">
148
+ <span class="micl-list-item__headline">Menu item</span>
149
+ </span>
150
+ </li>
151
+ </ul>
152
+ </nav>
153
+ </div>
154
+ ```
155
+
93
156
  ## Compatibility
94
157
  This component uses **popover anchor positioning** to place the menu next to its invoker. This is a modern CSS feature that may not be fully supported in all browsers. To ensure the menu works in browsers that do not support anchor positioning, wrap the menu and its invoker in a `<div>` element with `position:relative`. Please check [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/anchor#browser_compatibility) for details.
@@ -21,19 +21,25 @@
21
21
 
22
22
  @use '../../styles/elevation';
23
23
  @use '../../styles/motion';
24
- @use '../../styles/ripple';
25
24
  @use '../../styles/shapes';
26
- @use '../../styles/statelayer';
25
+
26
+ :root {
27
+ --md-sys-menu-motion-spatial: #{motion.$md-sys-motion-expressive-default-spatial};
28
+ --md-sys-menu-motion-duration: #{motion.$md-sys-motion-expressive-default-spatial-duration};
29
+ --md-sys-menu-motion-duration-reverse: #{motion.$md-sys-motion-expressive-fast-spatial-duration};
30
+ --md-sys-menu-width-max: 280px;
31
+ --md-sys-menu-width-min: 112px;
32
+ }
27
33
 
28
34
  .micl-menu[popover] {
29
35
  position: absolute;
30
36
  inset: unset;
31
37
  inset-block-start: anchor(end);
32
38
  inset-inline-start: anchor(start);
33
- position-try-fallbacks: flip-block, flip-inline;
34
- min-width: 112px;
35
- max-width: 280px;
36
- padding-inline: 0;
39
+ position-try: most-block-size flip-block, flip-inline;
40
+ min-width: var(--md-sys-menu-width-min);
41
+ max-width: var(--md-sys-menu-width-max);
42
+ padding: 0;
37
43
  border: none;
38
44
  border-radius: var(--md-sys-shape-corner-extra-small);
39
45
  background-color: var(--md-sys-color-surface-container);
@@ -41,33 +47,25 @@
41
47
  opacity: 0;
42
48
  overflow: hidden;
43
49
  transform: scaleY(0);
44
- transform-origin: top left;
50
+ transform-origin: left top;
45
51
  transition:
46
- opacity var(--md-sys-motion-duration-medium1),
47
- transform var(--md-sys-motion-duration-medium1),
48
- overlay var(--md-sys-motion-duration-medium1) allow-discrete,
49
- display var(--md-sys-motion-duration-medium1) allow-discrete;
52
+ opacity var(--md-sys-menu-motion-duration-reverse) linear,
53
+ transform var(--md-sys-menu-motion-duration-reverse) var(--md-sys-menu-motion-spatial),
54
+ overlay var(--md-sys-menu-motion-duration-reverse) linear allow-discrete,
55
+ display var(--md-sys-menu-motion-duration-reverse) linear allow-discrete;
50
56
 
51
57
  &:popover-open {
52
58
  opacity: 1;
53
59
  transform: scaleY(1);
54
60
  transition:
55
- opacity var(--md-sys-motion-duration-long2) motion.$md-sys-motion-easing-emphasized-decelerate,
56
- transform var(--md-sys-motion-duration-long2) linear(motion.$md-sys-motion-spring-default-spatial),
57
- overlay var(--md-sys-motion-duration-long2) linear allow-discrete,
58
- display var(--md-sys-motion-duration-long2) linear allow-discrete;
59
-
60
- @position-try-on {
61
- transform-origin: bottom left;
62
- }
61
+ opacity var(--md-sys-menu-motion-duration) motion.$md-sys-motion-easing-emphasized-decelerate,
62
+ transform var(--md-sys-menu-motion-duration) var(--md-sys-menu-motion-spatial),
63
+ overlay var(--md-sys-menu-motion-duration) linear allow-discrete,
64
+ display var(--md-sys-menu-motion-duration) linear allow-discrete;
63
65
 
64
66
  @starting-style {
65
67
  opacity: 0;
66
68
  transform: scaleY(0);
67
-
68
- @position-try-on {
69
- transform-origin: bottom left;
70
- }
71
69
  }
72
70
  &::backdrop {
73
71
  background-color: rgba(0, 0, 0, 0.2);
@@ -80,12 +78,13 @@
80
78
  &::backdrop {
81
79
  background-color: rgba(0, 0, 0, 0);
82
80
  transition:
83
- background-color var(--md-sys-motion-duration-long2),
84
- overlay var(--md-sys-motion-duration-long2) linear allow-discrete,
85
- display var(--md-sys-motion-duration-long2) linear allow-discrete;
81
+ background-color var(--md-sys-menu-motion-duration) linear,
82
+ overlay var(--md-sys-menu-motion-duration) linear allow-discrete,
83
+ display var(--md-sys-menu-motion-duration) linear allow-discrete;
86
84
  }
87
85
 
88
- .micl-list {
86
+ &> .micl-list {
87
+ --md-sys-list-padding: 4px;
89
88
  --md-sys-list-item-one-height: 48px;
90
89
  --md-sys-list-item-one-padding: 0;
91
90
  --md-sys-list-item-two-padding: 0;
@@ -95,18 +94,6 @@
95
94
  .micl-list-item-one,
96
95
  .micl-list-item-two,
97
96
  .micl-list-item-three {
98
- &:not(.micl-list-item--disabled) {
99
- --miclripple: 1;
100
-
101
- @include ripple.effect;
102
-
103
- cursor: pointer;
104
-
105
- &:focus-visible {
106
- outline-offset: calc(-1 * var(--md-sys-state-focus-indicator-thickness));
107
- z-index: 1;
108
- }
109
- }
110
97
  &.micl-list-item__divider {
111
98
  position: relative;
112
99
  margin-block-start: 16px;
@@ -122,6 +109,23 @@
122
109
  border-top: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
123
110
  }
124
111
  }
112
+ &> .micl-menu[popover] {
113
+ transform: scaleX(0);
114
+
115
+ &:popover-open {
116
+ transform: scaleX(1);
117
+
118
+ @starting-style {
119
+ transform: scaleX(0);
120
+ }
121
+ }
122
+ &:popover-open {
123
+ &::backdrop {
124
+ background-color: rgba(0, 0, 0, 0);
125
+ }
126
+ }
127
+ }
125
128
  }
126
129
  }
127
130
  }
131
+
@@ -21,27 +21,15 @@
21
21
 
22
22
  export const menuSelector = '.micl-menu[popover]';
23
23
 
24
- /**
25
- * Set the origin for menu transformations just before transitions start.
26
- * By default, the origin is "top left" (the menu opens just below the invoker, left aligned),
27
- * but could also be "top right", "bottom left" or "bottom right".
28
- * When the browser needs to apply a position-try-fallbacks, because there is not enough space
29
- * for the menu in the default location, then the reverse transformation will be applied from
30
- * the wrong origin.
31
- * Therefore, when the menu is open, calculate the transformation origin just before the
32
- * transitions start. When the menu is closed, do the same just after the 'display:none' has
33
- * been removed by the browser (the 'toggle' event has then been triggered).
34
- */
35
24
  export default (() =>
36
25
  {
37
26
  const getOrigin = (invoker: Element, popover: Element): string =>
38
27
  {
39
- const invokerY = invoker.getBoundingClientRect().y,
40
- popoverY = popover.getBoundingClientRect().y,
41
- oldOrigin = window.getComputedStyle(popover).getPropertyValue('transform-origin');
28
+ const invokerRect = invoker.getBoundingClientRect(),
29
+ popoverRect = popover.getBoundingClientRect();
42
30
 
43
- return ((invokerY > popoverY) ? 'bottom ' : 'top ') +
44
- ((parseInt(oldOrigin) > 0) ? 'right' : 'left');
31
+ return ((invokerRect.x > popoverRect.x) ? 'right ' : 'left ') +
32
+ ((invokerRect.y > popoverRect.y) ? 'bottom' : 'top');
45
33
  };
46
34
 
47
35
  return {
@@ -72,6 +60,49 @@ export default (() =>
72
60
  }
73
61
  });
74
62
 
63
+ element.querySelectorAll<HTMLButtonElement>(
64
+ ':scope > ul.micl-list > li > button[popovertarget]'
65
+ ).forEach(submenuinvoker =>
66
+ {
67
+ if (submenuinvoker.popoverTargetElement?.matches('.micl-menu[popover]')) {
68
+ let hoverTimeout: any,
69
+ id = `--${submenuinvoker.popoverTargetElement.id}`;
70
+
71
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
72
+ submenuinvoker.style.setProperty('anchor-name', id);
73
+ submenuinvoker.popoverTargetElement.style.insetBlockStart = `anchor(${id} start)`;
74
+ submenuinvoker.popoverTargetElement.style.insetInlineStart = `anchor(${id} end)`;
75
+ }
76
+
77
+ submenuinvoker.addEventListener('mouseenter', () =>
78
+ {
79
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
80
+ submenuinvoker.popoverTargetElement.showPopover();
81
+ }
82
+ });
83
+ submenuinvoker.addEventListener('mouseleave', () =>
84
+ {
85
+ hoverTimeout = setTimeout(() => {
86
+ if (
87
+ submenuinvoker.popoverTargetElement instanceof HTMLElement
88
+ && !submenuinvoker.popoverTargetElement.matches(':hover')
89
+ ) {
90
+ submenuinvoker.popoverTargetElement.hidePopover();
91
+ }
92
+ }, 100);
93
+ });
94
+ submenuinvoker.popoverTargetElement.addEventListener('mouseenter', () =>
95
+ {
96
+ clearTimeout(hoverTimeout);
97
+ });
98
+ submenuinvoker.popoverTargetElement.addEventListener('mouseleave', () =>
99
+ {
100
+ if (submenuinvoker.popoverTargetElement instanceof HTMLElement) {
101
+ submenuinvoker.popoverTargetElement.hidePopover();
102
+ }
103
+ });
104
+ }
105
+ });
75
106
  }
76
107
  };
77
108
  })();
@@ -0,0 +1,99 @@
1
+ # Side sheet
2
+ This component implements the the [Material Design 3 Expressive Side sheet](https://m3.material.io/components/side-sheets/overview) design.
3
+
4
+ ## Basic Usage
5
+
6
+ ### HTML
7
+ To create a standard side sheet, use the `<dialog>` element with the `popover` attribute. The `closedby="any"` attribute allows the user to dismiss the side sheet by clicking anywhere outside of it.
8
+
9
+ ```HTML
10
+ <dialog id="mysidesheet" class="micl-sidesheet" closedby="any" popover>
11
+ <div class="micl-sidesheet__headline">
12
+ <h2>Title</h2>
13
+ <button
14
+ type="button"
15
+ class="micl-iconbutton-s material-symbols-outlined"
16
+ popovertarget="mysidesheet"
17
+ aria-label="Close"
18
+ >close</button>
19
+ </div>
20
+ <div class="micl-sidesheet__content">
21
+ ...your content...
22
+ </div>
23
+ </dialog>
24
+ ```
25
+
26
+ ### CSS
27
+ Import the side sheet styles into your project:
28
+
29
+ ```CSS
30
+ @use "material-inspired-component-library/dist/sidesheet";
31
+ ```
32
+
33
+ ### JavaScript
34
+ No custom JavaScript is required for the core functionality of the side sheet component.
35
+
36
+ ### Demo
37
+ A live example of the [Side sheet component](https://henkpb.github.io/micl/sidesheet.html) is available for you to interact with.
38
+
39
+ ## Variants
40
+ A **modal** side sheet blocks access to the rest of the page and must be dismissed explicitly by the user. This is suitable for critical tasks or information that requires a user's full attention.
41
+
42
+ To create a modal side sheet, use the `<dialog>` element without the `popover` attribute. Use `closedby="closerequest"` to prevent the side sheet from being dismissed by clicking outside of it. You'll also need a button or other control with popovertarget to close it.
43
+
44
+ ```HTML
45
+ <dialog id="mysidesheet" class="micl-sidesheet" closedby="closerequest">
46
+ <div class="micl-sidesheet__headline">
47
+ <button
48
+ type="button"
49
+ class="micl-iconbutton-s material-symbols-outlined"
50
+ aria-label="Go back"
51
+ >arrow_back</button>
52
+ <h2>Title</h2>
53
+ <button
54
+ type="button"
55
+ class="micl-iconbutton-s material-symbols-outlined"
56
+ popovertarget="mysidesheet"
57
+ aria-label="Close"
58
+ >close</button>
59
+ </div>
60
+ <div class="micl-sidesheet__content">
61
+ ...your content...
62
+ </div>
63
+ <div class="micl-sidesheet__actions">
64
+ <button type="button" class="micl-button">Save</button>
65
+ </div>
66
+ </dialog>
67
+ ```
68
+
69
+ To open either a standard or modal side sheet, link a button to the side sheet's ID using the `popovertarget` attribute:
70
+ ```HTML
71
+ <button type="button" popovertarget="mysidesheet">Open Side Sheet</button>
72
+ ```
73
+
74
+ The back-button and the actions-container are optional. To remove the vertical divider of the "standard" side sheet, assign zero to the following CSS variable:
75
+ ```CSS
76
+ #mysidesheet {
77
+ --md-sys-sidesheet-divider-width: 0;
78
+ }
79
+ ```
80
+ To remove the horizontal divider of the actions-container:
81
+ ```CSS
82
+ #mysidesheet {
83
+ --md-sys-sidesheet-actions-divider-width: 0;
84
+ }
85
+ ```
86
+
87
+ ### Warning
88
+ The **standard** side sheet component adds CSS rules to the `<body>` element to properly resize the main content area when the side sheet is open. Overriding these rules may cause the component to behave unexpectedly. The rules that are applied are:
89
+
90
+ ```CSS
91
+ box-sizing: border-box;
92
+ margin-left: 0px;
93
+ margin-right: 0px;
94
+ max-width: ...varies depending on if the side sheet is opened...
95
+ transition: ...transition on max-width...
96
+ ```
97
+
98
+ ## Compatibility
99
+ 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,157 @@
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/typography';
26
+
27
+ dialog.micl-navigationrail {
28
+ --md-sys-navigationrail-width: 256px;
29
+ --md-sys-navigationrail-maxwidth: 400px;
30
+ --md-sys-navigationrail-spring-buffer: 200px;
31
+ --md-sys-navigationrail-padding-standard: 24px;
32
+ --md-sys-navigationrail-padding-modal: 16px;
33
+ --md-sys-navigationrail-motion-spatial: #{motion.$md-sys-motion-expressive-slow-spatial};
34
+ --md-sys-navigationrail-motion-duration: #{motion.$md-sys-motion-expressive-slow-spatial-duration};
35
+ --md-sys-navigationrail-motion-duration-reverse: #{motion.$md-sys-motion-expressive-default-spatial-duration};
36
+
37
+ box-sizing: border-box;
38
+ display: none;
39
+ flex-direction: column;
40
+ justify-content: space-between;
41
+ min-width: calc(var(--md-sys-navigationrail-width) + var(--md-sys-navigationrail-spring-buffer));
42
+ max-width: calc(var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer));
43
+ height: 100%;
44
+ min-height: 100%;
45
+ margin-block: 0;
46
+ margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
47
+ margin-inline-end: auto;
48
+ padding-block-start: 10px;
49
+ padding-block-end: var(--md-sys-navigationrail-padding-standard);
50
+ padding-inline-start: var(--md-sys-navigationrail-spring-buffer);
51
+ padding-inline-end: 0;
52
+ background-color: var(--md-sys-color-surface);
53
+ border: none;
54
+ box-shadow: var(--md-sys-elevation-level0);
55
+ opacity: 0;
56
+ overflow: hidden;
57
+ transition:
58
+ opacity var(--md-sys-navigationrail-motion-duration-reverse) linear,
59
+ margin-inline-start var(--md-sys-navigationrail-motion-duration-reverse) var(--md-sys-navigationrail-motion-spatial),
60
+ overlay var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete,
61
+ display var(--md-sys-navigationrail-motion-duration-reverse) linear allow-discrete;
62
+
63
+ .micl-navigationrail__headline {
64
+ display: flex;
65
+ align-items: center;
66
+ padding-inline-start: 12px;
67
+ padding-inline-end: 24px;
68
+ column-gap: 8px;
69
+ color: var(--md-sys-color-on-surface-variant);
70
+
71
+ h1, h2, h3, h4, h5, h6, .micl-heading {
72
+ @include typography.title-large;
73
+
74
+ flex: 1 2 fit-content;
75
+ margin: 0;
76
+ overflow: hidden;
77
+ text-overflow: ellipsis;
78
+ white-space: nowrap;
79
+ user-select: none;
80
+ }
81
+ }
82
+ .micl-navigationrail__content {
83
+ box-sizing: border-box;
84
+ display: flex;
85
+ flex-direction: column;
86
+ flex: 1 1 auto;
87
+ align-items: flex-start;
88
+ row-gap: 8px;
89
+ width: 100%;
90
+ max-width: 100%;
91
+ padding-inline: var(--md-sys-navigationrail-padding-standard);
92
+ overflow: hidden auto;
93
+ }
94
+ .micl-navigationrail__actions {
95
+ box-sizing: border-box;
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: start;
99
+ width: 100%;
100
+ max-width: 100%;
101
+ height: calc(72px - var(--md-sys-navigationrail-padding-standard));
102
+ margin: auto 0 0 0;
103
+ padding-block-start: 16px;
104
+ overflow: hidden;
105
+ border-block-start: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
106
+
107
+ button:active,
108
+ button:focus-visible,
109
+ button:hover {
110
+ color: var(--md-sys-color-primary);
111
+ }
112
+ }
113
+
114
+ &::backdrop {
115
+ background-color: rgba(0, 0, 0, 0);
116
+ transition:
117
+ background-color var(--md-sys-navigationrail-motion-duration) linear,
118
+ overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
119
+ display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
120
+ }
121
+ &[open] {
122
+ background-color: var(--md-sys-color-surface-container-low);
123
+ border-start-end-radius: var(--md-sys-shape-corner-large);
124
+ border-end-end-radius: var(--md-sys-shape-corner-large);
125
+ box-shadow: var(--md-sys-elevation-level1);
126
+
127
+ .micl-navigationrail__headline {
128
+ padding-inline-end: 4px;
129
+ }
130
+ }
131
+ &:popover-open {
132
+ border-inline-end: var(--md-sys-divider-thickness) solid var(--md-sys-divider-color);
133
+ }
134
+ &:popover-open,
135
+ &[open] {
136
+ display: flex;
137
+ margin-inline-start: calc(-1 * var(--md-sys-navigationrail-spring-buffer));
138
+ opacity: 1;
139
+ transition:
140
+ opacity var(--md-sys-navigationrail-motion-duration) linear,
141
+ margin-inline-start var(--md-sys-navigationrail-motion-duration) var(--md-sys-navigationrail-motion-spatial),
142
+ overlay var(--md-sys-navigationrail-motion-duration) linear allow-discrete,
143
+ display var(--md-sys-navigationrail-motion-duration) linear allow-discrete;
144
+
145
+ @starting-style {
146
+ margin-inline-start: calc(-1 * (var(--md-sys-navigationrail-maxwidth) + var(--md-sys-navigationrail-spring-buffer)));
147
+ opacity: 0;
148
+ }
149
+ }
150
+ &[open]::backdrop {
151
+ background-color: rgba(0, 0, 0, 0.2);
152
+
153
+ @starting-style {
154
+ background-color: rgba(0, 0, 0, 0);
155
+ }
156
+ }
157
+ }