mtrl 0.8.0-next.19 → 0.8.0-next.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtrl",
3
- "version": "0.8.0-next.19",
3
+ "version": "0.8.0-next.21",
4
4
  "description": "A functional TypeScript/JavaScript component library with composable architecture based on Material Design 3",
5
5
  "author": "floor",
6
6
  "license": "MIT License",
@@ -96,11 +96,18 @@ $component: "#{$prefix}-menu";
96
96
  @include m.state-layer(t.color("on-surface"), "hover");
97
97
  }
98
98
 
99
+ // The focus layer is for a person navigating by key. Focus moves into
100
+ // the menu however it was opened, so keying this off `:focus` marked
101
+ // the first item as soon as the menu appeared under the pointer, which
102
+ // reads as a highlight nobody asked for.
99
103
  &:focus {
100
- @include m.state-layer(t.color("on-surface"), "focus");
101
104
  outline: none;
102
105
  }
103
106
 
107
+ &:focus-visible {
108
+ @include m.state-layer(t.color("on-surface"), "focus");
109
+ }
110
+
104
111
  &:active {
105
112
  @include m.state-layer(t.color("on-surface"), "pressed");
106
113
  }
@@ -161,7 +168,7 @@ $component: "#{$prefix}-menu";
161
168
  @include m.state-layer(t.color("on-secondary-container"), "hover");
162
169
  }
163
170
 
164
- &:focus {
171
+ &:focus-visible {
165
172
  @include m.state-layer(t.color("on-secondary-container"), "focus");
166
173
  }
167
174
 
@@ -219,6 +226,25 @@ $component: "#{$prefix}-menu";
219
226
  text-overflow: ellipsis;
220
227
  }
221
228
 
229
+ // A label with a line under it. The stacking belongs to every
230
+ // variant, so a supporting line never runs into its label; the
231
+ // vertical menu adds its own type and colour on top.
232
+ &-label {
233
+ display: flex;
234
+ flex-direction: column;
235
+ justify-content: center;
236
+ flex: 1;
237
+ min-width: 0;
238
+ }
239
+
240
+ &-supporting {
241
+ @include m.typography("body-medium");
242
+ color: t.color("on-surface-variant");
243
+ white-space: nowrap;
244
+ overflow: hidden;
245
+ text-overflow: ellipsis;
246
+ }
247
+
222
248
  &-shortcut {
223
249
  margin-left: 12px;
224
250
  color: t.color("on-surface-variant");
@@ -286,6 +312,167 @@ $component: "#{$prefix}-menu";
286
312
  }
287
313
 
288
314
  // RTL Support
315
+ // -------------------------------------------------------------------------
316
+ // The M3 expressive vertical menu (Compose SegmentedMenuTokens and
317
+ // StandardMenuTokens / VibrantMenuTokens). A 16dp container holding 44dp
318
+ // items 2dp apart; an item is a 4dp rectangle at rest and rounds to 12dp
319
+ // as it is hovered, focused, pressed or selected, which is the expressive
320
+ // state this variant is for. The first and last items round to 12dp on
321
+ // their outer corners so the column reads as one block.
322
+ // -------------------------------------------------------------------------
323
+ &--vertical {
324
+ // Standard: surface-based, the lower-emphasis mapping
325
+ --#{$prefix}-menu-container: #{t.color("surface-container-low")};
326
+ --#{$prefix}-menu-label: #{t.color("on-surface")};
327
+ --#{$prefix}-menu-supporting: #{t.color("on-surface-variant")};
328
+ --#{$prefix}-menu-selected-container: #{t.color("tertiary-container")};
329
+ --#{$prefix}-menu-selected-label: #{t.color("on-tertiary-container")};
330
+
331
+ border-radius: v.shape("large");
332
+ background-color: var(--#{$prefix}-menu-container);
333
+ color: var(--#{$prefix}-menu-label);
334
+ padding: 8px;
335
+
336
+ // Vibrant: tertiary-based, more prominent, to be used sparingly
337
+ &.#{$component}--vibrant {
338
+ --#{$prefix}-menu-container: #{t.color("tertiary-container")};
339
+ --#{$prefix}-menu-label: #{t.color("on-tertiary-container")};
340
+ --#{$prefix}-menu-supporting: #{t.color("on-tertiary-container")};
341
+ --#{$prefix}-menu-selected-container: #{t.color("tertiary")};
342
+ --#{$prefix}-menu-selected-label: #{t.color("on-tertiary")};
343
+ }
344
+
345
+ .#{$component}-list {
346
+ display: flex;
347
+ flex-direction: column;
348
+ gap: 2px; // SegmentedGap
349
+ }
350
+
351
+ .#{$component}-item {
352
+ @include m.typography("body-large");
353
+ min-height: 44px; // SegmentedMenuTokens.Item
354
+ padding: 8px 16px; // ItemTopSpace / ItemLeadingSpace
355
+ padding-inline-end: 16px;
356
+ color: var(--#{$prefix}-menu-label);
357
+ border-radius: v.shape("extra-small"); // ItemShape
358
+ transition:
359
+ border-radius v.motion("spring-fast-spatial-duration")
360
+ v.motion("spring-fast-spatial-easing"),
361
+ background-color v.motion("duration-short2")
362
+ v.motion("easing-standard");
363
+
364
+ // The shape is the state: 4dp at rest, 12dp once it is touched
365
+ &:hover,
366
+ &:focus-visible,
367
+ &:active {
368
+ border-radius: v.shape("medium");
369
+ }
370
+
371
+ // The ends of the column round outwards, so the items read as one
372
+ &:first-child {
373
+ border-start-start-radius: v.shape("medium");
374
+ border-start-end-radius: v.shape("medium");
375
+ }
376
+
377
+ &:last-child {
378
+ border-end-start-radius: v.shape("medium");
379
+ border-end-end-radius: v.shape("medium");
380
+ }
381
+
382
+ &--selected {
383
+ background-color: var(--#{$prefix}-menu-selected-container);
384
+ color: var(--#{$prefix}-menu-selected-label);
385
+ border-radius: v.shape("medium"); // ItemSelectedShape
386
+
387
+ &:hover {
388
+ @include m.state-layer(var(--#{$prefix}-menu-selected-label), "hover");
389
+ }
390
+
391
+ &:focus-visible {
392
+ @include m.state-layer(var(--#{$prefix}-menu-selected-label), "focus");
393
+ }
394
+
395
+ &:active {
396
+ @include m.state-layer(var(--#{$prefix}-menu-selected-label), "pressed");
397
+ }
398
+ }
399
+
400
+ &--disabled {
401
+ color: color-mix(in srgb, var(--#{$prefix}-menu-label) 38%, transparent);
402
+ }
403
+
404
+ &-icon {
405
+ color: var(--#{$prefix}-menu-supporting);
406
+ margin-inline-end: 12px; // ItemBetweenSpace
407
+
408
+ svg {
409
+ // ItemLeadingIconSize / ItemTrailingIconSize
410
+ width: 20px;
411
+ height: 20px;
412
+ }
413
+ }
414
+
415
+ &-shortcut {
416
+ @include m.typography("label-small"); // ItemTrailingSupportingTextFont
417
+ color: var(--#{$prefix}-menu-supporting);
418
+ }
419
+
420
+ // A label with a line under it
421
+ &-label {
422
+ display: flex;
423
+ flex-direction: column;
424
+ justify-content: center;
425
+ flex: 1;
426
+ min-width: 0;
427
+ }
428
+
429
+ &-supporting {
430
+ @include m.typography("body-medium"); // ItemSupportingTextFont
431
+ color: var(--#{$prefix}-menu-supporting);
432
+ white-space: nowrap;
433
+ overflow: hidden;
434
+ text-overflow: ellipsis;
435
+ }
436
+
437
+ &--selected {
438
+ .#{$component}-item-icon,
439
+ .#{$component}-item-shortcut,
440
+ .#{$component}-item-supporting {
441
+ color: inherit;
442
+ }
443
+ }
444
+ }
445
+
446
+ // A grouped menu separates its runs of items with a divider; the gap
447
+ // treatment the spec shows is not offered on the web
448
+ // (m3.material.io menu guidelines, "Gaps & dividers")
449
+ .#{$component}-divider {
450
+ margin: 6px 0;
451
+ }
452
+ }
453
+
454
+ // -------------------------------------------------------------------------
455
+ // Shape morph on the container: while a submenu is open, the menu that
456
+ // opened it steps back to an 8dp corner and the active one takes 24dp
457
+ // (SegmentedMenuTokens.ActiveContainerShape and InactiveContainerShape).
458
+ // This is the expressive active state the spec describes.
459
+ // -------------------------------------------------------------------------
460
+ &--vertical {
461
+ transition:
462
+ transform v.motion("duration-medium1") v.motion("easing-emphasized"),
463
+ opacity v.motion("duration-medium1") v.motion("easing-emphasized"),
464
+ border-radius v.motion("spring-fast-spatial-duration")
465
+ v.motion("spring-fast-spatial-easing");
466
+
467
+ &.#{$component}--active {
468
+ border-radius: 24px;
469
+ }
470
+
471
+ &.#{$component}--inactive {
472
+ border-radius: v.shape("small");
473
+ }
474
+ }
475
+
289
476
  @include m.rtl {
290
477
  transform-origin: top right;
291
478