@expressivecss/expressive 0.2.0 → 0.4.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 (80) hide show
  1. package/README.md +8 -8
  2. package/dist/css/expressive.css +1915 -1566
  3. package/dist/css/expressive.css.map +1 -1
  4. package/dist/css/expressive.min.css +1 -1
  5. package/dist/css/expressive.min.css.map +1 -1
  6. package/dist/js/expressive.cjs +1338 -1528
  7. package/dist/js/expressive.cjs.map +4 -4
  8. package/dist/js/expressive.js +1338 -1528
  9. package/dist/js/expressive.js.map +4 -4
  10. package/dist/js/expressive.min.js +10 -20
  11. package/dist/js/expressive.min.js.map +4 -4
  12. package/dist/js/expressive.mjs +1338 -1529
  13. package/dist/js/expressive.mjs.map +4 -4
  14. package/dist/types/components/autocomplete.d.ts +2 -9
  15. package/dist/types/components/buttons.d.ts +19 -43
  16. package/dist/types/components/cards.d.ts +3 -6
  17. package/dist/types/components/carousel.d.ts +42 -48
  18. package/dist/types/components/characterCounter.d.ts +3 -5
  19. package/dist/types/components/chips.d.ts +4 -4
  20. package/dist/types/components/collapsible.d.ts +28 -23
  21. package/dist/types/components/datepicker.d.ts +2 -8
  22. package/dist/types/components/dropdown.d.ts +11 -2
  23. package/dist/types/components/index.d.ts +0 -1
  24. package/dist/types/components/lightbox.d.ts +2 -2
  25. package/dist/types/components/parallax.d.ts +7 -37
  26. package/dist/types/components/pushpin.d.ts +2 -2
  27. package/dist/types/components/range.d.ts +2 -2
  28. package/dist/types/components/registry.d.ts +0 -4
  29. package/dist/types/components/scrollspy.d.ts +26 -50
  30. package/dist/types/components/select.d.ts +20 -6
  31. package/dist/types/components/sidenav.d.ts +40 -55
  32. package/dist/types/components/slider.d.ts +2 -2
  33. package/dist/types/components/tabs.d.ts +2 -2
  34. package/dist/types/components/tapTarget.d.ts +25 -26
  35. package/dist/types/components/timepicker.d.ts +2 -4
  36. package/dist/types/components/tooltip.d.ts +2 -2
  37. package/dist/types/core/component.d.ts +4 -4
  38. package/dist/types/index.d.ts +1 -1
  39. package/package.json +2 -2
  40. package/src/sass/README.md +3 -6
  41. package/src/sass/abstracts/_breakpoints.scss +0 -16
  42. package/src/sass/abstracts/_variables.scss +0 -21
  43. package/src/sass/base/_grid.scss +0 -19
  44. package/src/sass/components/_badges.scss +6 -5
  45. package/src/sass/components/_breadcrumb.scss +93 -16
  46. package/src/sass/components/_buttons.scss +212 -145
  47. package/src/sass/components/_cards.scss +50 -123
  48. package/src/sass/components/_carousel.scss +128 -63
  49. package/src/sass/components/_chips.scss +1 -1
  50. package/src/sass/components/_collapsible.scss +158 -60
  51. package/src/sass/components/_collection.scss +146 -80
  52. package/src/sass/components/_datepicker.scss +1 -15
  53. package/src/sass/components/_dropdown.scss +110 -14
  54. package/src/sass/components/_icons-material-design.scss +77 -4
  55. package/src/sass/components/_index.scss +1 -0
  56. package/src/sass/components/_lightbox.scss +4 -0
  57. package/src/sass/components/_modal.scss +13 -31
  58. package/src/sass/components/_navbar.scss +24 -6
  59. package/src/sass/components/_page-footer.scss +134 -15
  60. package/src/sass/components/_pagination.scss +131 -25
  61. package/src/sass/components/_parallax.scss +96 -21
  62. package/src/sass/components/_preloader.scss +145 -300
  63. package/src/sass/components/_scrollspy.scss +18 -0
  64. package/src/sass/components/_sidenav.scss +230 -119
  65. package/src/sass/components/_slider.scss +8 -0
  66. package/src/sass/components/_table_of_contents.scss +30 -14
  67. package/src/sass/components/_tabs.scss +54 -35
  68. package/src/sass/components/_tapTarget.scss +128 -45
  69. package/src/sass/components/_toast.scss +10 -11
  70. package/src/sass/components/_toolbar.scss +2 -2
  71. package/src/sass/components/_tooltip.scss +4 -9
  72. package/src/sass/components/_transitions.scss +0 -5
  73. package/src/sass/components/forms/_index.scss +0 -5
  74. package/src/sass/components/forms/_input-fields.scss +49 -52
  75. package/src/sass/components/forms/_select.scss +175 -60
  76. package/src/sass/components/forms/_switches.scss +21 -8
  77. package/src/sass/utilities/_helpers.scss +1 -3
  78. package/src/sass/utilities/_typescale.scss +0 -5
  79. package/src/sass/utilities/_visibility.scss +2 -2
  80. package/dist/types/components/modal.d.ts +0 -45
@@ -1,29 +1,106 @@
1
1
  @use "../abstracts" as *;
2
2
 
3
+ // Breadcrumbs. Anatomy is the HTML: a <nav> whose child is an <ol> of
4
+ // links. The last crumb is the current page (aria-current="page").
5
+ // .breadcrumb / .breadcrumb-wrapper stay as aliases.
6
+ //
7
+ // Tokens:
8
+ // --md-comp-breadcrumb-label-color ancestors
9
+ // --md-comp-breadcrumb-current-color current page
10
+ // --md-comp-breadcrumb-separator "/"
11
+ // --md-comp-breadcrumb-gap 8px
12
+ //
13
+ // Nest descendants inside this block. `#{$_crumb} > ol` would only attach
14
+ // `> ol` to the last item in the list (same bug as the icon size classes).
15
+
16
+ nav:has(> ol):not(.pagination),
17
+ nav:has(> .breadcrumb),
3
18
  .breadcrumb-wrapper {
19
+ --md-comp-breadcrumb-label-color: var(--md-sys-color-on-surface-variant);
20
+ --md-comp-breadcrumb-current-color: var(--md-sys-color-on-surface);
21
+ --md-comp-breadcrumb-separator: "/";
22
+ --md-comp-breadcrumb-gap: 8px;
23
+
4
24
  display: flex;
25
+ flex-wrap: wrap;
5
26
  align-items: center;
6
- }
27
+ margin: 0;
28
+ padding: 0;
29
+ color: var(--md-comp-breadcrumb-label-color);
30
+ @include typescale("body-small");
7
31
 
8
- .breadcrumb {
9
- display: inline-flex;
10
- align-items: center;
32
+ &.nowrap {
33
+ flex-wrap: nowrap;
34
+ overflow-x: auto;
35
+ scrollbar-width: none;
36
+
37
+ &::-webkit-scrollbar {
38
+ display: none;
39
+ }
40
+ }
41
+
42
+ > ol {
43
+ display: flex;
44
+ flex-wrap: inherit;
45
+ align-items: center;
46
+ list-style: none;
47
+ min-width: 0;
48
+ margin: 0;
49
+ padding: 0;
50
+
51
+ > li {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ min-width: 0;
55
+ }
11
56
 
12
- i,
13
- i.material-icons, i.material-symbols-outlined,
14
- i.material-symbols-rounded, i.material-symbols-sharp,
15
- &:before {
16
- font-weight: normal;
17
- font-style: normal;
18
- font-size: 24px;
57
+ > li:has(> [aria-current="page"]) {
58
+ flex-shrink: 0;
59
+ }
60
+
61
+ // Separator before every crumb after the first. A real character, not
62
+ // a private-use icon-font slot — no Symbols file required.
63
+ > li + li::before {
64
+ content: var(--md-comp-breadcrumb-separator);
65
+ margin-inline: var(--md-comp-breadcrumb-gap);
66
+ color: var(--md-comp-breadcrumb-label-color);
67
+ }
68
+ }
69
+
70
+ > .breadcrumb + .breadcrumb::before {
71
+ content: var(--md-comp-breadcrumb-separator);
72
+ margin-inline: var(--md-comp-breadcrumb-gap);
73
+ color: var(--md-comp-breadcrumb-label-color);
74
+ }
75
+
76
+ :is(a, .breadcrumb) {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ min-height: 32px;
80
+ color: var(--md-comp-breadcrumb-label-color);
81
+ text-decoration: none;
82
+ @include focus-visible;
83
+
84
+ &:hover {
85
+ color: var(--md-comp-breadcrumb-current-color);
86
+ }
19
87
  }
20
88
 
21
- &:before {
22
- content: '\E5CC';
23
- font-family: 'Material Symbols Outlined', 'Material Symbols Rounded', 'Material Symbols Sharp', 'Material Icons';
89
+ [aria-current="page"] {
90
+ color: var(--md-comp-breadcrumb-current-color);
24
91
  }
25
92
 
26
- &:first-child:before {
27
- visibility: hidden;
93
+ i {
94
+ font-size: 1.125em;
95
+ margin-inline-end: 4px;
28
96
  }
29
97
  }
98
+
99
+ // Inside a top app bar the trail follows the bar, not the muted ancestor
100
+ // pair. Loose .breadcrumb links in the bar are already excluded from
101
+ // destination styling in _navbar.scss.
102
+ header:has(> nav) > nav:has(> ol):not(.pagination),
103
+ header:has(> nav) > nav:has(> .breadcrumb) {
104
+ --md-comp-breadcrumb-label-color: inherit;
105
+ --md-comp-breadcrumb-current-color: inherit;
106
+ }
@@ -2,10 +2,10 @@
2
2
 
3
3
  // Common buttons and FABs.
4
4
  //
5
- // Anatomy is the HTML. A <button> (or <a class="button"> / .btn) is a filled
6
- // common button. Put an <i> first or last for a leading/trailing icon — no
7
- // icon-left / icon-right required. Icon-only is a 40dp icon button. Helpers
8
- // switch the M3 variant (tonal, outlined, elevated, text) or the size.
5
+ // Anatomy is the HTML. A <button> (or <a class="button">) is a filled
6
+ // common button. Put an <i> first or last for a leading/trailing icon.
7
+ // Icon-only is a 40dp icon button. Helpers switch the M3 variant
8
+ // (tonal, outlined, elevated, text) or the size.
9
9
  //
10
10
  // Tokens follow https://m3.material.io/components/buttons/specs
11
11
  // height 40 / 32 small / 56 large, label-large, 20dp stadium
@@ -28,7 +28,7 @@
28
28
  // Widget chrome that happens to be a <button> — not a common button.
29
29
  $_not-btn: ".datepicker-day-button, .month-prev, .month-next, .indicator-item-btn";
30
30
 
31
- $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-small";
31
+ $_btn: "button:not(#{$_not-btn}), a.button";
32
32
 
33
33
  :where(#{$_btn}) {
34
34
  @include btn;
@@ -69,7 +69,7 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
69
69
  }
70
70
 
71
71
  // Default variant is filled. :where() keeps specificity at zero so .tonal etc. win.
72
- :where(#{$_btn}):not(.tonal, .outlined, .border, .elevated, .text, .transparent, .btn-flat) {
72
+ :where(#{$_btn}):not(.tonal, .outlined, .elevated, .text) {
73
73
  @include btn-filled;
74
74
  }
75
75
 
@@ -77,8 +77,7 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
77
77
  @include btn-tonal;
78
78
  }
79
79
 
80
- :where(#{$_btn}).outlined,
81
- :where(#{$_btn}).border {
80
+ :where(#{$_btn}).outlined {
82
81
  @include btn-outlined;
83
82
  }
84
83
 
@@ -86,20 +85,12 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
86
85
  @include btn-elevated;
87
86
  }
88
87
 
89
- :where(#{$_btn}).text,
90
- :where(#{$_btn}).transparent,
91
- .btn-flat {
88
+ :where(#{$_btn}).text {
92
89
  @include btn-flat;
93
90
  }
94
91
 
95
- // icon-right is a compat alias: new markup puts the icon last in the DOM.
96
- :where(#{$_btn}).icon-right {
97
- flex-direction: row-reverse;
98
- }
99
-
100
92
  // Sizes. small = 32dp, large/extra = 56dp (M3 extra-large / FAB height).
101
- :where(#{$_btn}).small,
102
- .btn-small {
93
+ :where(#{$_btn}).small {
103
94
  --md-comp-filled-button-container-height: 32px;
104
95
  --md-comp-filled-button-container-shape: 16px;
105
96
  --md-comp-filled-button-leading-space: 16px;
@@ -111,8 +102,7 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
111
102
  }
112
103
 
113
104
  :where(#{$_btn}).large,
114
- :where(#{$_btn}).extra,
115
- .btn-large {
105
+ :where(#{$_btn}).extra {
116
106
  --md-comp-filled-button-container-height: 56px;
117
107
  --md-comp-filled-button-container-shape: 28px;
118
108
  --md-comp-filled-button-leading-space: 24px;
@@ -126,11 +116,6 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
126
116
  border-radius: 9999px;
127
117
  }
128
118
 
129
- .btn-block {
130
- display: flex;
131
- width: 100%;
132
- }
133
-
134
119
  // Extended FAB: 56dp, large corners, primary-container, icon + label.
135
120
  :where(#{$_btn}).extend {
136
121
  height: 56px;
@@ -168,13 +153,10 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
168
153
  }
169
154
  }
170
155
 
171
- // FAB. .btn-floating is the JS contract (FloatingActionButton looks it up).
172
- // Icon-only .extra / .large is the same 56dp regular FAB. Bare .btn-floating
173
- // is the 40dp small FAB.
174
- .btn-floating,
156
+ // FAB. Icon-only .extra / .large is the 56dp regular FAB. Add .small for
157
+ // the 40dp small FAB. The speed-dial host is .fixed-action-btn.
175
158
  :where(#{$_btn}).extra.circle,
176
- :where(#{$_btn}).large.circle,
177
- :where(#{$_btn}).btn-large.circle {
159
+ :where(#{$_btn}).large.circle {
178
160
  display: inline-flex;
179
161
  align-items: center;
180
162
  justify-content: center;
@@ -191,7 +173,6 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
191
173
  vertical-align: middle;
192
174
  @include z-depth("3");
193
175
  @include focus-visible;
194
- transition: background-color .2s ease-out, box-shadow .2s ease-out;
195
176
 
196
177
  > i {
197
178
  font-size: 24px;
@@ -219,8 +200,7 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
219
200
  );
220
201
  }
221
202
 
222
- &.small,
223
- &.btn-small {
203
+ &.small {
224
204
  width: 40px;
225
205
  height: 40px;
226
206
  border-radius: 12px;
@@ -232,100 +212,184 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
232
212
 
233
213
  &.halfway-fab {
234
214
  position: absolute;
235
- right: 24px;
215
+ inset-inline-end: 24px;
236
216
  bottom: -28px;
237
217
 
238
218
  &.left {
239
- right: auto;
240
- left: 24px;
219
+ inset-inline-end: auto;
220
+ inset-inline-start: 24px;
241
221
  }
242
222
  }
243
223
  }
244
224
 
245
- // Small FAB alias: .btn-floating alone is 40dp (historical size + M3 small).
246
- .btn-floating:not(.large, .btn-large, .extra, .small, .btn-small) {
247
- width: 40px;
248
- height: 40px;
249
- border-radius: 12px;
250
-
251
- &.halfway-fab {
252
- bottom: -20px;
253
- }
254
- }
255
-
256
225
  :where(#{$_btn}):disabled,
257
226
  :where(#{$_btn})[disabled],
258
- :where(#{$_btn}).disabled,
259
- .btn-floating:disabled,
260
- .btn-floating[disabled],
261
- .btn-floating.disabled {
227
+ :where(#{$_btn}).disabled {
262
228
  @include btn-disabled;
263
229
  }
264
230
 
265
- // Fixed Action Button — JS-driven menu around a FAB.
231
+ // Speed dial. .active (and :hover when the pointer can hover) opens the
232
+ // menu. Motion is CSS. .click-to-toggle is the markup switch for click
233
+ // mode. .fixed-action-btn stays the public class.
234
+ //
235
+ // Tokens:
236
+ // --md-comp-fab-offset 16px from the corner
237
+ // --md-comp-fab-z 997
238
+ // --md-comp-fab-menu-gap 16px
239
+ // --md-comp-fab-duration 200ms
240
+ // --md-comp-fab-stagger 40ms
241
+ // --md-comp-fab-easing soft ease-in-out
242
+ // --md-comp-fab-travel center-to-center step into the main disc
243
+ // --md-comp-fab-hidden-transform toward / into the main button
266
244
  .fixed-action-btn {
245
+ --md-comp-fab-offset: 16px;
246
+ --md-comp-fab-z: 997;
247
+ --md-comp-fab-menu-gap: 16px;
248
+ --md-comp-fab-duration: 200ms;
249
+ --md-comp-fab-stagger: 40ms;
250
+ --md-comp-fab-easing: cubic-bezier(0.65, 0, 0.35, 1);
251
+ --md-comp-fab-travel: 64px;
252
+ --md-comp-fab-hidden-transform: scale(0)
253
+ translateY(calc(var(--md-comp-fab-travel) * (var(--i, 0) + 1)));
254
+
267
255
  position: fixed;
268
- right: 23px;
269
- bottom: 23px;
270
- padding-top: 15px;
271
- margin-bottom: 0;
272
- z-index: 997;
273
-
274
- &.active {
275
- ul {
276
- visibility: visible;
277
- padding-left: 0;
278
- list-style-type: none;
256
+ inset-inline-end: var(--md-comp-fab-offset);
257
+ bottom: var(--md-comp-fab-offset);
258
+ z-index: var(--md-comp-fab-z);
259
+ padding-top: var(--md-comp-fab-menu-gap);
260
+ margin: 0;
261
+ overflow: visible;
262
+
263
+ // Main disc stays above retracting actions so they slide under it.
264
+ > :is(a, button) {
265
+ position: relative;
266
+ z-index: 1;
267
+ }
268
+
269
+ :is(ul, menu) {
270
+ --n: 1;
271
+ position: absolute;
272
+ inset-inline: 0;
273
+ bottom: 64px;
274
+ display: flex;
275
+ flex-direction: column;
276
+ align-items: center;
277
+ gap: var(--md-comp-fab-menu-gap);
278
+ margin: 0;
279
+ padding: 0;
280
+ list-style: none;
281
+ visibility: hidden;
282
+ overflow: visible;
283
+ transition: visibility 0s
284
+ calc(var(--md-comp-fab-duration) + var(--md-comp-fab-stagger) * (var(--n) - 1));
285
+
286
+ &:has(> :nth-child(2)) { --n: 2; }
287
+ &:has(> :nth-child(3)) { --n: 3; }
288
+ &:has(> :nth-child(4)) { --n: 4; }
289
+ &:has(> :nth-child(5)) { --n: 5; }
290
+ &:has(> :nth-child(6)) { --n: 6; }
291
+ &:has(> :nth-child(7)) { --n: 7; }
292
+ &:has(> :nth-child(8)) { --n: 8; }
293
+
294
+ li:nth-last-child(1) { --i: 0; }
295
+ li:nth-last-child(2) { --i: 1; }
296
+ li:nth-last-child(3) { --i: 2; }
297
+ li:nth-last-child(4) { --i: 3; }
298
+ li:nth-last-child(5) { --i: 4; }
299
+ li:nth-last-child(6) { --i: 5; }
300
+ li:nth-last-child(7) { --i: 6; }
301
+ li:nth-last-child(8) { --i: 7; }
302
+
303
+ > li > :is(a, button) {
304
+ opacity: 0;
305
+ transform: var(--md-comp-fab-hidden-transform);
306
+ transition:
307
+ opacity var(--md-comp-fab-duration) var(--md-comp-fab-easing),
308
+ transform var(--md-comp-fab-duration) var(--md-comp-fab-easing),
309
+ background-color .2s ease-out,
310
+ box-shadow .2s ease-out;
311
+ // Close: farthest first, so they funnel into the disc.
312
+ transition-delay: calc(
313
+ var(--md-comp-fab-stagger) * (var(--n) - 1 - var(--i, 0))
314
+ );
315
+ }
316
+ }
317
+
318
+ &.active :is(ul, menu) {
319
+ visibility: visible;
320
+ transition-delay: 0s;
321
+
322
+ > li > :is(a, button) {
323
+ opacity: 1;
324
+ transform: none;
325
+ transition-delay: calc(var(--md-comp-fab-stagger) * var(--i, 0));
326
+ }
327
+ }
328
+
329
+ // Closest-to-FAB is the first child when the menu is left, right, or
330
+ // down (row-reverse / row / column). Top uses nth-last-child above.
331
+ &.direction-left,
332
+ &.direction-right,
333
+ &.direction-bottom {
334
+ :is(ul, menu) {
335
+ li:nth-child(1) { --i: 0; }
336
+ li:nth-child(2) { --i: 1; }
337
+ li:nth-child(3) { --i: 2; }
338
+ li:nth-child(4) { --i: 3; }
339
+ li:nth-child(5) { --i: 4; }
340
+ li:nth-child(6) { --i: 5; }
341
+ li:nth-child(7) { --i: 6; }
342
+ li:nth-child(8) { --i: 7; }
279
343
  }
280
344
  }
281
345
 
282
346
  &.direction-left,
283
347
  &.direction-right {
284
- padding: 0 0 0 15px;
348
+ padding: 0;
285
349
 
286
- ul {
287
- text-align: right;
288
- right: 64px;
350
+ :is(ul, menu) {
351
+ inset: auto;
289
352
  top: 50%;
290
- transform: translateY(-50%);
291
- height: 100%;
292
- left: auto;
293
- width: 500px;
353
+ translate: 0 -50%;
354
+ flex-direction: row;
355
+ width: max-content;
356
+ height: auto;
357
+ }
358
+ }
294
359
 
295
- li {
296
- display: inline-block;
297
- margin: 7.5px 15px 0 0;
298
- }
360
+ // Hidden offset is toward the main button, one step per index, so
361
+ // close sends every action into the disc.
362
+ &.direction-left {
363
+ --md-comp-fab-hidden-transform: scale(0)
364
+ translateX(calc(var(--md-comp-fab-travel) * (var(--i, 0) + 1)));
365
+ padding-inline-start: var(--md-comp-fab-menu-gap);
366
+
367
+ :is(ul, menu) {
368
+ inset-inline-end: 64px;
369
+ flex-direction: row-reverse;
299
370
  }
300
371
  }
301
372
 
302
373
  &.direction-right {
303
- padding: 0 15px 0 0;
304
-
305
- ul {
306
- text-align: left;
307
- direction: rtl;
308
- left: 64px;
309
- right: auto;
374
+ --md-comp-fab-hidden-transform: scale(0)
375
+ translateX(calc(-1 * var(--md-comp-fab-travel) * (var(--i, 0) + 1)));
376
+ padding-inline-end: var(--md-comp-fab-menu-gap);
310
377
 
311
- li {
312
- margin: 7.5px 0 0 15px;
313
- }
378
+ :is(ul, menu) {
379
+ inset-inline-start: 64px;
314
380
  }
315
381
  }
316
382
 
317
383
  &.direction-bottom {
318
- padding: 0 0 15px 0;
384
+ --md-comp-fab-hidden-transform: scale(0)
385
+ translateY(calc(-1 * var(--md-comp-fab-travel) * (var(--i, 0) + 1)));
386
+ padding: 0 0 var(--md-comp-fab-menu-gap);
319
387
 
320
- ul {
388
+ :is(ul, menu) {
389
+ inset: auto;
321
390
  top: 64px;
322
391
  bottom: auto;
323
- display: flex;
324
- flex-direction: column-reverse;
325
-
326
- li {
327
- margin: 15px 0 0 0;
328
- }
392
+ inset-inline: 0;
329
393
  }
330
394
  }
331
395
 
@@ -333,75 +397,78 @@ $_btn: "button:not(#{$_not-btn}), a.button, .btn, .btn-flat, .btn-large, .btn-sm
333
397
  padding: 0;
334
398
  height: 56px;
335
399
 
336
- &.active {
337
- & > a i,
338
- & > button i {
339
- opacity: 0;
340
- }
400
+ :is(ul, menu) > li > :is(a, button) {
401
+ opacity: 1;
402
+ transform: none;
403
+ transition: opacity var(--md-comp-fab-duration);
341
404
  }
342
405
 
343
- ul {
344
- display: flex;
345
- top: 0;
406
+ &.active {
407
+ inset-inline: 0;
346
408
  bottom: 0;
347
- z-index: 1;
409
+ width: 100%;
410
+ height: 56px;
348
411
 
349
- li {
350
- flex: 1;
351
- display: inline-block;
352
- margin: 0;
412
+ > :is(a, button) > i {
413
+ opacity: 0;
414
+ }
415
+
416
+ :is(ul, menu) {
417
+ visibility: visible;
418
+ position: static;
419
+ display: flex;
420
+ flex-direction: row;
421
+ width: 100%;
353
422
  height: 100%;
354
- transition: none;
355
-
356
- a,
357
- button {
358
- display: block;
359
- overflow: hidden;
360
- position: relative;
361
- width: 100%;
362
- height: 100%;
363
- background-color: transparent;
364
- box-shadow: none;
365
- color: var(--md-sys-color-on-primary-container);
366
- line-height: 56px;
367
- z-index: 1;
368
-
369
- i {
370
- line-height: inherit;
371
- }
372
- }
423
+ gap: 0;
373
424
  }
374
425
  }
375
- }
376
426
 
377
- ul {
378
- left: 0;
379
- right: 0;
380
- text-align: center;
381
- position: absolute;
382
- bottom: 64px;
383
- margin: 0;
384
- visibility: hidden;
385
-
386
- li {
387
- margin-bottom: 15px;
388
- }
427
+ :is(ul, menu) li {
428
+ flex: 1;
429
+ margin: 0;
430
+ height: 100%;
389
431
 
390
- a.btn-floating,
391
- button.btn-floating {
392
- opacity: 0;
432
+ :is(a, button) {
433
+ display: grid;
434
+ place-items: center;
435
+ width: 100%;
436
+ height: 100%;
437
+ background: transparent;
438
+ box-shadow: none;
439
+ color: var(--md-sys-color-on-primary-container);
440
+ }
393
441
  }
394
442
  }
395
443
 
396
444
  .fab-backdrop {
397
445
  position: absolute;
398
- top: 0;
399
- left: 0;
446
+ inset: 0 auto auto 0;
400
447
  z-index: -1;
401
448
  width: 56px;
402
449
  height: 56px;
403
- background-color: var(--md-sys-color-primary-container);
404
450
  border-radius: 16px;
451
+ background-color: var(--md-sys-color-primary-container);
405
452
  transform: scale(0);
406
453
  }
407
454
  }
455
+
456
+ @media (hover: hover) {
457
+ .fixed-action-btn:not(.click-to-toggle):hover :is(ul, menu) {
458
+ visibility: visible;
459
+ transition-delay: 0s;
460
+
461
+ > li > :is(a, button) {
462
+ opacity: 1;
463
+ transform: none;
464
+ transition-delay: calc(var(--md-comp-fab-stagger) * var(--i, 0));
465
+ }
466
+ }
467
+ }
468
+
469
+ @media (prefers-reduced-motion: reduce) {
470
+ .fixed-action-btn {
471
+ --md-comp-fab-duration: 0s;
472
+ --md-comp-fab-stagger: 0s;
473
+ }
474
+ }