material 3.4.3 → 3.5.1

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 (178) hide show
  1. package/README.md +2 -2
  2. package/dist/elements/css/badge.css +1 -1
  3. package/dist/elements/css/badge.js +1 -1
  4. package/dist/elements/css/bottom-app-bar.css +1 -1
  5. package/dist/elements/css/bottom-app-bar.js +1 -1
  6. package/dist/elements/css/card.css +1 -1
  7. package/dist/elements/css/card.js +1 -1
  8. package/dist/elements/css/datepicker.css +1 -1
  9. package/dist/elements/css/datepicker.js +1 -1
  10. package/dist/elements/css/dialog.css +1 -1
  11. package/dist/elements/css/dialog.js +1 -1
  12. package/dist/elements/css/drawer.css +1 -1
  13. package/dist/elements/css/drawer.js +1 -1
  14. package/dist/elements/css/extended-fab.css +1 -1
  15. package/dist/elements/css/extended-fab.js +1 -1
  16. package/dist/elements/css/fab-menu.css +1 -1
  17. package/dist/elements/css/fab-menu.js +1 -1
  18. package/dist/elements/css/fab.css +1 -1
  19. package/dist/elements/css/fab.js +1 -1
  20. package/dist/elements/css/navigation-bar.css +1 -1
  21. package/dist/elements/css/navigation-bar.js +1 -1
  22. package/dist/elements/css/navigation-rail.css +1 -1
  23. package/dist/elements/css/navigation-rail.js +1 -1
  24. package/dist/elements/css/side-sheet.css +1 -1
  25. package/dist/elements/css/side-sheet.js +1 -1
  26. package/dist/elements/css/split-button.css +1 -1
  27. package/dist/elements/css/split-button.js +1 -1
  28. package/dist/elements/css/tabs.css +1 -1
  29. package/dist/elements/css/tabs.js +1 -1
  30. package/dist/elements/css/toolbar.css +1 -1
  31. package/dist/elements/css/toolbar.js +1 -1
  32. package/dist/elements/css/top-app-bar.css +1 -1
  33. package/dist/elements/css/top-app-bar.js +1 -1
  34. package/dist/elements/preupgrade/badge.css +1 -1
  35. package/dist/elements/preupgrade/bottom-app-bar.css +1 -1
  36. package/dist/elements/preupgrade/bottom-sheet.css +1 -1
  37. package/dist/elements/preupgrade/button-group.css +1 -1
  38. package/dist/elements/preupgrade/button.css +1 -1
  39. package/dist/elements/preupgrade/card.css +1 -1
  40. package/dist/elements/preupgrade/carousel.css +1 -1
  41. package/dist/elements/preupgrade/checkbox.css +1 -1
  42. package/dist/elements/preupgrade/chips.css +1 -1
  43. package/dist/elements/preupgrade/datepicker.css +1 -1
  44. package/dist/elements/preupgrade/dialog.css +1 -1
  45. package/dist/elements/preupgrade/divider.css +1 -1
  46. package/dist/elements/preupgrade/drawer.css +1 -1
  47. package/dist/elements/preupgrade/extended-fab.css +1 -1
  48. package/dist/elements/preupgrade/fab-menu.css +1 -1
  49. package/dist/elements/preupgrade/fab.css +1 -1
  50. package/dist/elements/preupgrade/icon-button.css +1 -1
  51. package/dist/elements/preupgrade/list.css +1 -1
  52. package/dist/elements/preupgrade/loading-indicator.css +1 -1
  53. package/dist/elements/preupgrade/menu.css +1 -1
  54. package/dist/elements/preupgrade/navigation-bar.css +1 -1
  55. package/dist/elements/preupgrade/navigation-rail.css +1 -1
  56. package/dist/elements/preupgrade/progress.css +1 -1
  57. package/dist/elements/preupgrade/radios.css +1 -1
  58. package/dist/elements/preupgrade/search.css +1 -1
  59. package/dist/elements/preupgrade/select.css +1 -1
  60. package/dist/elements/preupgrade/side-sheet.css +1 -1
  61. package/dist/elements/preupgrade/slider.css +1 -1
  62. package/dist/elements/preupgrade/snackbar.css +1 -1
  63. package/dist/elements/preupgrade/split-button.css +1 -1
  64. package/dist/elements/preupgrade/switch.css +1 -1
  65. package/dist/elements/preupgrade/tabs.css +1 -1
  66. package/dist/elements/preupgrade/text-field.css +1 -1
  67. package/dist/elements/preupgrade/timepicker.css +1 -1
  68. package/dist/elements/preupgrade/toolbar.css +1 -1
  69. package/dist/elements/preupgrade/tooltip.css +1 -1
  70. package/dist/elements/preupgrade/top-app-bar.css +1 -1
  71. package/dist/elements/preupgrade.css +1 -1
  72. package/dist/package.json +1 -1
  73. package/dist/ssr/react.js +179 -33
  74. package/dist/styles/badge.css +2 -2
  75. package/dist/styles/base.css +1 -1
  76. package/dist/styles/bottom-app-bar.css +2 -2
  77. package/dist/styles/bottom-sheet.css +2 -2
  78. package/dist/styles/button-group.css +1 -1
  79. package/dist/styles/button.css +1 -1
  80. package/dist/styles/card.css +2 -2
  81. package/dist/styles/carousel.css +1 -1
  82. package/dist/styles/checkbox.css +1 -1
  83. package/dist/styles/chips.css +2 -2
  84. package/dist/styles/contrast.css +1 -1
  85. package/dist/styles/datepicker.css +2 -2
  86. package/dist/styles/dialog.css +2 -2
  87. package/dist/styles/divider.css +1 -1
  88. package/dist/styles/drawer.css +2 -2
  89. package/dist/styles/extended-fab.css +2 -2
  90. package/dist/styles/fab-menu.css +2 -2
  91. package/dist/styles/fab.css +2 -2
  92. package/dist/styles/icon-button.css +1 -1
  93. package/dist/styles/list.css +2 -2
  94. package/dist/styles/loading-indicator.css +1 -1
  95. package/dist/styles/menu.css +2 -2
  96. package/dist/styles/navigation-bar.css +2 -2
  97. package/dist/styles/navigation-rail.css +2 -2
  98. package/dist/styles/progress.css +2 -2
  99. package/dist/styles/radios.css +1 -1
  100. package/dist/styles/search.css +1 -1
  101. package/dist/styles/select.css +1 -1
  102. package/dist/styles/side-sheet.css +2 -2
  103. package/dist/styles/slider.css +1 -1
  104. package/dist/styles/snackbar.css +2 -2
  105. package/dist/styles/split-button.css +2 -2
  106. package/dist/styles/switch.css +2 -2
  107. package/dist/styles/tabs.css +2 -2
  108. package/dist/styles/text-field.css +1 -1
  109. package/dist/styles/timepicker.css +1 -1
  110. package/dist/styles/toolbar.css +2 -2
  111. package/dist/styles/tooltip.css +1 -1
  112. package/dist/styles/top-app-bar.css +2 -2
  113. package/dist/styles/typography.css +1 -1
  114. package/dist/styles/utilities.css +1 -1
  115. package/dist/styles.css +2 -2
  116. package/dist/themes/autumn-contrast.css +1 -1
  117. package/dist/themes/autumn.css +1 -1
  118. package/dist/themes/baseline-contrast.css +1 -1
  119. package/dist/themes/baseline.css +1 -1
  120. package/dist/themes/brownbeige-contrast.css +1 -1
  121. package/dist/themes/brownbeige.css +1 -1
  122. package/dist/themes/content-contrast.css +1 -1
  123. package/dist/themes/content.css +1 -1
  124. package/dist/themes/desert-contrast.css +1 -1
  125. package/dist/themes/desert.css +1 -1
  126. package/dist/themes/expressive-contrast.css +1 -1
  127. package/dist/themes/expressive.css +1 -1
  128. package/dist/themes/fidelity-contrast.css +1 -1
  129. package/dist/themes/fidelity.css +1 -1
  130. package/dist/themes/forest-contrast.css +1 -1
  131. package/dist/themes/forest.css +1 -1
  132. package/dist/themes/fruit-salad-contrast.css +1 -1
  133. package/dist/themes/fruit-salad.css +1 -1
  134. package/dist/themes/highcontrast-contrast.css +1 -1
  135. package/dist/themes/highcontrast.css +1 -1
  136. package/dist/themes/monochrome-contrast.css +1 -1
  137. package/dist/themes/monochrome.css +1 -1
  138. package/dist/themes/neutral-contrast.css +1 -1
  139. package/dist/themes/neutral.css +1 -1
  140. package/dist/themes/ocean-contrast.css +1 -1
  141. package/dist/themes/ocean.css +1 -1
  142. package/dist/themes/rainbow-contrast.css +1 -1
  143. package/dist/themes/rainbow.css +1 -1
  144. package/dist/themes/sageivory-contrast.css +1 -1
  145. package/dist/themes/sageivory.css +1 -1
  146. package/dist/themes/spring-contrast.css +1 -1
  147. package/dist/themes/spring.css +1 -1
  148. package/dist/themes/summer-contrast.css +1 -1
  149. package/dist/themes/summer.css +1 -1
  150. package/dist/themes/sunset-contrast.css +1 -1
  151. package/dist/themes/sunset.css +1 -1
  152. package/dist/themes/tealcaramel-contrast.css +1 -1
  153. package/dist/themes/tealcaramel.css +1 -1
  154. package/dist/themes/vibrant-contrast.css +1 -1
  155. package/dist/themes/vibrant.css +1 -1
  156. package/package.json +5 -2
  157. package/src/styles/abstract/_direction.scss +196 -0
  158. package/src/styles/abstract/_emit.scss +20 -0
  159. package/src/styles/abstract/_mixins.scss +27 -10
  160. package/src/styles/components/_bottom-sheet.scss +4 -4
  161. package/src/styles/components/_chips.scss +23 -3
  162. package/src/styles/components/_datepicker.scss +65 -11
  163. package/src/styles/components/_extended-fab.scss +8 -12
  164. package/src/styles/components/_fab-menu.scss +20 -48
  165. package/src/styles/components/_fab.scss +8 -12
  166. package/src/styles/components/_list.scss +13 -4
  167. package/src/styles/components/_menu.scss +8 -8
  168. package/src/styles/components/_navigation-bar.scss +34 -7
  169. package/src/styles/components/_navigation-rail.scss +45 -12
  170. package/src/styles/components/_progress.scss +15 -1
  171. package/src/styles/components/_side-sheet.scss +30 -4
  172. package/src/styles/components/_snackbar.scss +6 -2
  173. package/src/styles/components/_split-button.scss +74 -36
  174. package/src/styles/components/_switch.scss +27 -7
  175. package/src/styles/components/_toolbar.scss +6 -2
  176. package/src/styles/abstract/_config.scss +0 -28
  177. package/src/styles/base/_foundation.scss +0 -4
  178. package/src/styles/base/_typescale.scss +0 -9
@@ -3,6 +3,7 @@
3
3
  @use '../abstract/theme' as t;
4
4
  @use '../abstract/mixins' as m;
5
5
  @use '../abstract/variables' as v;
6
+ @use '../abstract/direction' as d;
6
7
 
7
8
  // M3 Expressive navigation rail.
8
9
  // Geometry: Compose NavigationRailCollapsed/Expanded/BaselineItem/VerticalItem/
@@ -127,7 +128,7 @@ $snap: 0s linear $midpoint;
127
128
  position: absolute;
128
129
  z-index: -1;
129
130
  inset-block-start: 6px;
130
- inset-inline-start: 20px;
131
+ @include d.start(20px, $arm: false);
131
132
  inline-size: 56px;
132
133
  block-size: 32px;
133
134
  border-radius: v.shape('full'); // NavigationRailTokens active-indicator-shape
@@ -197,7 +198,7 @@ $snap: 0s linear $midpoint;
197
198
  display: grid;
198
199
  place-items: center;
199
200
  inset-block-start: 10px;
200
- inset-inline-start: 36px;
201
+ @include d.start(36px, $arm: false);
201
202
  inline-size: 24px;
202
203
  block-size: 24px;
203
204
  color: t.color('on-surface-variant');
@@ -214,16 +215,19 @@ $snap: 0s linear $midpoint;
214
215
  position: absolute;
215
216
  box-sizing: border-box;
216
217
  inset-block-start: 42px;
217
- inset-inline-start: 16px;
218
+ @include d.start(16px, $arm: false);
218
219
  inline-size: 64px;
219
220
  text-align: center;
220
221
  white-space: nowrap;
221
222
  overflow: hidden;
222
223
  text-overflow: ellipsis;
223
224
  @include m.typography('label-medium');
225
+ // The inline inset's transition names both physical sides in the arms
226
+ // form (d.transition): the arms swap which is live, and a transition
227
+ // that names a property the arms unset jumps instead of snapping.
224
228
  transition:
225
229
  inset-block-start $snap,
226
- inset-inline-start $snap,
230
+ d.transition(inset-inline-start, $snap),
227
231
  inline-size $snap,
228
232
  font-size $snap,
229
233
  line-height $snap,
@@ -233,7 +237,7 @@ $snap: 0s linear $midpoint;
233
237
  }
234
238
  &--expanded &__label {
235
239
  inset-block-start: 18px;
236
- inset-inline-start: 68px;
240
+ @include d.start(68px, $arm: false);
237
241
  inline-size: calc(100% - 104px);
238
242
  text-align: start;
239
243
  @include m.typography('label-large');
@@ -252,7 +256,7 @@ $snap: 0s linear $midpoint;
252
256
  &__badge {
253
257
  position: absolute;
254
258
  box-sizing: border-box;
255
- inset-inline-start: 48px;
259
+ @include d.start(48px, $arm: false);
256
260
  inset-block-start: 8px;
257
261
  min-inline-size: 16px;
258
262
  min-block-size: 16px;
@@ -261,7 +265,8 @@ $snap: 0s linear $midpoint;
261
265
  background: t.color('error');
262
266
  color: t.color('on-error');
263
267
  @include m.typography('label-small');
264
- transition: inset-inline-start $snap, inset-inline-end $snap, inset-block-start $snap;
268
+ // Both physical sides in the arms form, as the label's snap above.
269
+ transition: d.transition(inset-inline-start, $snap), inset-block-start $snap;
265
270
  transition-behavior: allow-discrete;
266
271
  &--dot {
267
272
  inline-size: 6px;
@@ -269,13 +274,31 @@ $snap: 0s linear $midpoint;
269
274
  min-inline-size: 0;
270
275
  min-block-size: 0;
271
276
  padding: 0;
272
- inset-inline-start: 54px;
277
+ @include d.start(54px, $arm: false);
273
278
  inset-block-start: 10px;
274
279
  }
275
280
  }
276
- &--expanded &__badge { inset-inline-start: auto; inset-inline-end: 36px; inset-block-start: 20px; }
281
+ &--expanded &__badge { @include d.sides(auto, 36px, $arm: false); inset-block-start: 20px; }
277
282
  &--expanded &__badge--dot { inset-block-start: 25px; }
278
283
 
284
+ // The start-edge insets above are the left-to-right form; these arms write
285
+ // the mirrored one, a marker on the rail root included. Nothing of this in
286
+ // the logical form, where the insets mirror natively.
287
+ @include d.arms-selector('.#{$component}__indicator') { right: 20px; left: auto; }
288
+ @include d.arms-selector('.#{$component}__icon') { right: 36px; left: auto; }
289
+ @include d.arms-selector('.#{$component}__label') { right: 16px; left: auto; }
290
+ @include d.arms-selector('.#{$component}__badge') { right: 48px; left: auto; }
291
+ @include d.arms-selector('.#{$component}__badge--dot') { right: 54px; left: auto; }
292
+
293
+ // The expanded rules carry the variant class, so a marker on the root
294
+ // needs the self form (the fab-menu bottom-start trap).
295
+ &--expanded {
296
+ @include d.arms($self: true) {
297
+ .#{$component}__label { right: 68px; left: auto; }
298
+ .#{$component}__badge { left: 36px; right: auto; }
299
+ }
300
+ }
301
+
279
302
  &--hide-collapsed:not(&--expanded) { display: none; }
280
303
 
281
304
  // Modal expanded rail: a native dialog docked to the start edge.
@@ -283,7 +306,7 @@ $snap: 0s linear $midpoint;
283
306
  &--modal {
284
307
  position: fixed;
285
308
  inset-block: 0;
286
- inset-inline: 0 auto;
309
+ @include d.sides(0, auto, $arm: false);
287
310
  margin: 0;
288
311
  border: 0;
289
312
  max-inline-size: calc(100vw - 56px);
@@ -291,12 +314,22 @@ $snap: 0s linear $midpoint;
291
314
  block-size: 100dvh;
292
315
  background: t.color('surface-container');
293
316
  // The modal rail's container, corner-large at the end, as the drawer's
294
- border-start-end-radius: v.shape('large');
295
- border-end-end-radius: v.shape('large');
317
+ @include d.corners($start-end: v.shape('large'), $end-end: v.shape('large'), $arm: false);
296
318
  transition: inline-size $fast-spatial;
297
319
  @include m.elevation(2);
298
320
  &:not([open]) { display: none; }
299
321
  &::backdrop { background: t.alpha('scrim', 0.32); }
322
+
323
+ // The modal docks at the start edge and its large corners follow it. One
324
+ // arm carries the whole mirrored form; the logical form needs none of it.
325
+ @include d.arms($self: true) {
326
+ left: auto;
327
+ right: 0;
328
+ border-top-left-radius: v.shape('large');
329
+ border-bottom-left-radius: v.shape('large');
330
+ border-top-right-radius: 0;
331
+ border-bottom-right-radius: 0;
332
+ }
300
333
  }
301
334
 
302
335
  &__toggle:focus-visible { outline: 2px solid t.color('secondary'); outline-offset: -2px; }
@@ -8,6 +8,7 @@
8
8
  @use "../../styles/abstract/variables" as v;
9
9
  @use "../../styles/abstract/functions" as f;
10
10
  @use "../../styles/abstract/mixins" as m;
11
+ @use "../../styles/abstract/direction" as d;
11
12
  @use "../../styles/abstract/theme" as t;
12
13
 
13
14
  $component: "#{base.$prefix}-progress";
@@ -58,7 +59,7 @@ $component: "#{base.$prefix}-progress";
58
59
  white-space: nowrap;
59
60
 
60
61
  .#{$component}--linear & {
61
- inset-inline-end: 0;
62
+ @include d.end(0, $arm: false);
62
63
  top: 100%;
63
64
  margin-top: 4px;
64
65
  }
@@ -70,6 +71,19 @@ $component: "#{base.$prefix}-progress";
70
71
  }
71
72
  }
72
73
 
74
+ // The label's mirrored inset, in one arm that also covers a marker on this
75
+ // root: --linear and the runtime's direction mark are the same element, and
76
+ // the plain arm members need the marker on an ancestor
77
+ // (abstract/_direction.scss). Nothing of it in the logical form.
78
+ &--linear {
79
+ @include d.arms($self: true) {
80
+ .#{$component}__label {
81
+ right: auto;
82
+ left: 0;
83
+ }
84
+ }
85
+ }
86
+
73
87
  // A linear indicator with a label leaves room for it underneath
74
88
  &--linear:has(.#{$component}__label) {
75
89
  margin-bottom: 20px;
@@ -4,6 +4,7 @@
4
4
  @use "../abstract/variables" as v;
5
5
  @use "../abstract/mixins" as m;
6
6
  @use "../abstract/theme" as t;
7
+ @use "../abstract/direction" as d;
7
8
 
8
9
  $component: "#{base.$prefix}-side-sheet";
9
10
 
@@ -181,14 +182,39 @@ $component: "#{base.$prefix}-side-sheet";
181
182
  // Sheet.Side.Docked.Container.Shape = Corner.None),
182
183
  &.#{$component}--end .#{$component}__container {
183
184
  box-shadow: f.get-elevation(1), calc(m.$sheet-overshoot-guard * var(--#{$component}-direction)) 0 0 0 t.color("surface-container-low");
184
- border-start-start-radius: v.shape("large");
185
- border-end-start-radius: v.shape("large");
185
+ @include d.corners($start-start: v.shape("large"), $end-start: v.shape("large"), $arm: false);
186
186
  }
187
187
 
188
188
  &.#{$component}--start .#{$component}__container {
189
189
  box-shadow: f.get-elevation(1), calc(-1 * m.$sheet-overshoot-guard * var(--#{$component}-direction)) 0 0 0 t.color("surface-container-low");
190
- border-start-end-radius: v.shape("large");
191
- border-end-end-radius: v.shape("large");
190
+ @include d.corners($start-end: v.shape("large"), $end-end: v.shape("large"), $arm: false);
191
+ }
192
+
193
+ // The inner edge follows the direction, so the mirrored form is an
194
+ // arm: the base corners are unset there, not mirrored by the cascade.
195
+ // One arm per placement, written after its base, the marker on the
196
+ // sheet root included (the self form). Nothing of it in the logical
197
+ // form, where the corners mirror natively.
198
+ &.#{$component}--end {
199
+ @include d.arms($self: true) {
200
+ .#{$component}__container {
201
+ border-top-left-radius: 0;
202
+ border-bottom-left-radius: 0;
203
+ border-top-right-radius: v.shape("large");
204
+ border-bottom-right-radius: v.shape("large");
205
+ }
206
+ }
207
+ }
208
+
209
+ &.#{$component}--start {
210
+ @include d.arms($self: true) {
211
+ .#{$component}__container {
212
+ border-top-right-radius: 0;
213
+ border-bottom-right-radius: 0;
214
+ border-top-left-radius: v.shape("large");
215
+ border-bottom-left-radius: v.shape("large");
216
+ }
217
+ }
192
218
  }
193
219
  }
194
220
 
@@ -12,6 +12,7 @@
12
12
  @use '../../styles/abstract/variables' as v;
13
13
  @use '../../styles/abstract/functions' as f;
14
14
  @use '../../styles/abstract/mixins' as m;
15
+ @use '../../styles/abstract/direction' as d;
15
16
  @use '../../styles/abstract/theme' as t;
16
17
 
17
18
  $component: '#{base.$prefix}-snackbar';
@@ -74,12 +75,15 @@ $margin: 16px;
74
75
  translate: -50% 0;
75
76
  }
76
77
 
78
+ // The placement class sits on this root, which the runtime may also mark:
79
+ // the self form covers a marker on the snackbar itself
80
+ // (abstract/_direction.scss).
77
81
  &--start {
78
- inset-inline-start: $margin;
82
+ @include d.start($margin, $self: true);
79
83
  }
80
84
 
81
85
  &--end {
82
- inset-inline-end: $margin;
86
+ @include d.end($margin, $self: true);
83
87
  }
84
88
 
85
89
  // ---------------------------------------------------------------------------
@@ -8,8 +8,15 @@
8
8
  // becomes a circle while its menu is open, and its chevron turns 180 degrees.
9
9
  //
10
10
  // Both halves are the library's own button, so their colours, state layers,
11
- // focus rings and touch targets come from there. Everything is written with
12
- // logical properties, so the pair mirrors in right-to-left languages.
11
+ // focus rings and touch targets come from there.
12
+ //
13
+ // The corners are written as the logical properties and go through the
14
+ // direction switch (abstract/_direction.scss): the runtime-adopted sheets
15
+ // keep the logical radii, and the artefacts a consumer bundler lowers carry
16
+ // the physical pair with the right-to-left pair as a direction arm, so the
17
+ // bundler's :lang() lowering cannot pin them to the left-to-left corners of a
18
+ // right-to-left page. The radii themselves are custom properties, so a state
19
+ // changes only their value and the arms keep choosing the pair.
13
20
  @use "sass:map";
14
21
  @use "sass:math";
15
22
  @use "../../styles/abstract/base" as base;
@@ -17,6 +24,7 @@
17
24
  @use "../../styles/abstract/functions" as f;
18
25
  @use "../../styles/abstract/mixins" as m;
19
26
  @use "../../styles/abstract/theme" as t;
27
+ @use "../../styles/abstract/direction" as d;
20
28
 
21
29
  $component: "#{base.$prefix}-split-button";
22
30
  $button: "#{base.$prefix}-button";
@@ -56,6 +64,13 @@ $gap: 2px;
56
64
  // side overflow it, so a 9999px pill beside a 4dp corner drags that corner
57
65
  // to about a fiftieth of a pixel and the split reads as a square cut.
58
66
  // Half the height is the same pill and leaves the inner corner alone.
67
+ //
68
+ // The size classes set the three radii; a root without one keeps the
69
+ // default size's values, which is the size the factory defaults to.
70
+ --#{$component}-pill: #{math.div(map.get($sizes, "s", "height"), 2)};
71
+ --#{$component}-corner: var(--#{$component}-inner-shape, #{map.get($sizes, "s", "inner")});
72
+ --#{$component}-corner-active: var(--#{$component}-inner-shape-active, #{map.get($sizes, "s", "inner-active")});
73
+
59
74
  .#{$button} {
60
75
  transition:
61
76
  border-radius v.motion("spring-fast-spatial-duration") v.motion("spring-fast-spatial-easing"),
@@ -67,21 +82,13 @@ $gap: 2px;
67
82
  // ---------------------------------------------------------------------------
68
83
  @each $size, $spec in $sizes {
69
84
  &--#{$size} {
70
- $inner: var(--#{base.$prefix}-split-button-inner-shape, #{map.get($spec, "inner")});
71
- $inner-active: var(
72
- --#{base.$prefix}-split-button-inner-shape-active,
73
- #{map.get($spec, "inner-active")}
74
- );
75
-
76
- $outer: math.div(map.get($spec, "height"), 2);
85
+ --#{$component}-pill: #{math.div(map.get($spec, "height"), 2)};
86
+ --#{$component}-corner: var(--#{$component}-inner-shape, #{map.get($spec, "inner")});
87
+ --#{$component}-corner-active: var(--#{$component}-inner-shape-active, #{map.get($spec, "inner-active")});
77
88
 
78
89
  .#{$button} {
79
90
  height: map.get($spec, "height");
80
91
  min-height: map.get($spec, "height");
81
- border-start-start-radius: $outer;
82
- border-end-start-radius: $outer;
83
- border-start-end-radius: $outer;
84
- border-end-end-radius: $outer;
85
92
  }
86
93
 
87
94
  // The leading button: an outer pill edge, an inner corner facing its
@@ -90,15 +97,6 @@ $gap: 2px;
90
97
  padding-inline: map.get($spec, "lead-start") map.get($spec, "lead-end");
91
98
  // Compose SplitButtonDefaults.LeadingButtonMinWidth
92
99
  min-width: 48px;
93
- border-start-end-radius: $inner;
94
- border-end-end-radius: $inner;
95
-
96
- &:hover,
97
- &:focus-visible,
98
- &:active {
99
- border-start-end-radius: $inner-active;
100
- border-end-end-radius: $inner-active;
101
- }
102
100
  }
103
101
 
104
102
  // The trailing button is symmetrical, so its icon is nudged towards the
@@ -108,8 +106,6 @@ $gap: 2px;
108
106
  padding-inline: map.get($spec, "trail");
109
107
  // Its width is its padding and its icon, not the button's own minimum
110
108
  min-width: 0;
111
- border-start-start-radius: $inner;
112
- border-end-start-radius: $inner;
113
109
 
114
110
  // The icon sits in the button's icon wrapper, which has a size of its
115
111
  // own; the split button's chevron is bigger than a button icon
@@ -129,20 +125,62 @@ $gap: 2px;
129
125
  translate: map.get($spec, "offset") 0;
130
126
  }
131
127
  }
132
-
133
- &:hover,
134
- &:focus-visible,
135
- &:active {
136
- border-start-start-radius: $inner-active;
137
- border-end-start-radius: $inner-active;
138
- }
139
128
  }
129
+ }
130
+ }
140
131
 
141
- // Open: the trailing button's inner corner rounds off into a circle
142
- &.#{$component}--expanded .#{$component}__trailing {
143
- border-start-start-radius: $outer;
144
- border-end-start-radius: $outer;
145
- }
132
+ // ---------------------------------------------------------------------------
133
+ // The corners: the outer pair faces out, the inner pair faces the gap. The
134
+ // leading half's inner corners sit on its trailing edge and the trailing
135
+ // half's on its leading edge, so the right-to-left form swaps the pair.
136
+ // ---------------------------------------------------------------------------
137
+ .#{$button} {
138
+ border-radius: var(--#{$component}-pill);
139
+ }
140
+
141
+ .#{$component}__leading {
142
+ @include d.corners(
143
+ $start-start: var(--#{$component}-pill),
144
+ $start-end: var(--#{$component}-corner),
145
+ $end-start: var(--#{$component}-pill),
146
+ $end-end: var(--#{$component}-corner),
147
+ );
148
+ }
149
+
150
+ .#{$component}__trailing {
151
+ @include d.corners(
152
+ $start-start: var(--#{$component}-corner),
153
+ $start-end: var(--#{$component}-pill),
154
+ $end-start: var(--#{$component}-corner),
155
+ $end-end: var(--#{$component}-pill),
156
+ );
157
+ }
158
+
159
+ // The inner corner grows further while a half is hovered, focused or
160
+ // pressed. Only the value changes, so the arms keep choosing the pair.
161
+ .#{$component}__leading:where(:hover, :focus-visible, :active),
162
+ .#{$component}__trailing:where(:hover, :focus-visible, :active) {
163
+ --#{$component}-corner: var(--#{$component}-corner-active);
164
+ }
165
+
166
+ // Open: the trailing button's inner corner rounds off into a circle. The
167
+ // pill is the same on either side, so this needs no arm.
168
+ &--expanded .#{$component}__trailing {
169
+ --#{$component}-corner: var(--#{$component}-pill);
170
+ }
171
+
172
+ // The placement class and the direction marker are the same element here:
173
+ // the runtime writes mtrl-rtl on this root, and dir="rtl" may sit on it.
174
+ // The arms above need a strict ancestor, so the root-carried form is
175
+ // written here, after them (abstract/_direction.scss: nothing in the
176
+ // logical form, where the radii mirror natively).
177
+ @include d.arms-self-only {
178
+ .#{$component}__leading {
179
+ border-radius: var(--#{$component}-corner) var(--#{$component}-pill) var(--#{$component}-pill) var(--#{$component}-corner);
180
+ }
181
+
182
+ .#{$component}__trailing {
183
+ border-radius: var(--#{$component}-pill) var(--#{$component}-corner) var(--#{$component}-corner) var(--#{$component}-pill);
146
184
  }
147
185
  }
148
186
 
@@ -4,6 +4,7 @@
4
4
  @use '../../styles/abstract/functions' as f;
5
5
  @use '../../styles/abstract/mixins' as m;
6
6
  @use '../../styles/abstract/theme' as t;
7
+ @use '../../styles/abstract/direction' as d;
7
8
 
8
9
  $component: '#{base.$prefix}-switch';
9
10
 
@@ -112,7 +113,7 @@ $component: '#{base.$prefix}-switch';
112
113
  width: 40px;
113
114
  height: 40px;
114
115
  top: -6px;
115
- inset-inline-start: -6px;
116
+ @include d.start-value(--#{$component}-layer-start, -6px);
116
117
  background-color: t.color('on-surface');
117
118
  opacity: 0;
118
119
  border-radius: 50%;
@@ -138,7 +139,7 @@ $component: '#{base.$prefix}-switch';
138
139
  &__thumb {
139
140
  position: absolute;
140
141
  top: 6px;
141
- inset-inline-start: 6px;
142
+ @include d.start-value(--#{$component}-thumb-start, 6px);
142
143
  width: 16px;
143
144
  height: 16px;
144
145
  border-radius: 50%;
@@ -190,7 +191,7 @@ $component: '#{base.$prefix}-switch';
190
191
  width: 24px;
191
192
  height: 24px;
192
193
  top: 2px;
193
- inset-inline-start: 2px;
194
+ @include d.start-value-set(--#{$component}-thumb-start, 2px);
194
195
  }
195
196
 
196
197
  .#{$component}__thumb-icon--unselected {
@@ -206,7 +207,7 @@ $component: '#{base.$prefix}-switch';
206
207
  border-color: t.color('primary');
207
208
 
208
209
  &::after {
209
- inset-inline-start: 14px;
210
+ @include d.start-value-set(--#{$component}-layer-start, 14px);
210
211
  background-color: t.color('primary');
211
212
  }
212
213
  }
@@ -216,7 +217,7 @@ $component: '#{base.$prefix}-switch';
216
217
  width: 24px;
217
218
  height: 24px;
218
219
  top: 2px;
219
- inset-inline-start: 22px;
220
+ @include d.start-value-set(--#{$component}-thumb-start, 22px);
220
221
  }
221
222
 
222
223
  .#{$component}__thumb-icon:not(.#{$component}__thumb-icon--unselected) {
@@ -308,11 +309,30 @@ $component: '#{base.$prefix}-switch';
308
309
  width: 28px;
309
310
  height: 28px;
310
311
  top: 0;
311
- inset-inline-start: 0;
312
+ @include d.start-value-set(--#{$component}-thumb-start, 0);
312
313
  }
313
314
 
314
315
  &.#{$component}--checked .#{$component}__input:active ~ .#{$component}__track .#{$component}__thumb {
315
- inset-inline-start: 20px;
316
+ @include d.start-value-set(--#{$component}-thumb-start, 20px);
317
+ }
318
+ }
319
+
320
+ // The mirrored handle and layer positions, one arm per subject: every
321
+ // state's move rides the custom property the arms form's base names, and a
322
+ // bundler lowers no custom property, so the move animates on whichever side
323
+ // the direction placed it — the transitions above already name both sides
324
+ // in the arms form. The arm resets the base side to auto, exactly as the
325
+ // logical property resolves one side per direction. Nothing of it in the
326
+ // logical form, where the insets mirror natively.
327
+ @include d.arms($self: true) {
328
+ .#{$component}__track::after {
329
+ left: auto;
330
+ right: var(--#{$component}-layer-start, -6px);
331
+ }
332
+
333
+ .#{$component}__thumb {
334
+ left: auto;
335
+ right: var(--#{$component}-thumb-start, 6px);
316
336
  }
317
337
  }
318
338
 
@@ -11,6 +11,7 @@
11
11
  @use '../../styles/abstract/variables' as v;
12
12
  @use '../../styles/abstract/functions' as f;
13
13
  @use '../../styles/abstract/mixins' as m;
14
+ @use '../../styles/abstract/direction' as d;
14
15
  @use '../../styles/abstract/theme' as t;
15
16
 
16
17
  $component: '#{base.$prefix}-toolbar';
@@ -143,12 +144,15 @@ $component: '#{base.$prefix}-toolbar';
143
144
  max-height: calc(100% - 2 * var(--#{$component}-margin));
144
145
  }
145
146
 
147
+ // The placement class sits on this root, which the runtime may also mark:
148
+ // the self form covers a marker on the toolbar itself
149
+ // (abstract/_direction.scss).
146
150
  &--start {
147
- inset-inline-start: var(--#{$component}-margin);
151
+ @include d.start(var(--#{$component}-margin), $self: true);
148
152
  }
149
153
 
150
154
  &--end {
151
- inset-inline-end: var(--#{$component}-margin);
155
+ @include d.end(var(--#{$component}-margin), $self: true);
152
156
  }
153
157
 
154
158
  &--floating.#{$component}--bottom {
@@ -1,28 +0,0 @@
1
- // src/styles/abstract/_config.scss
2
- @use 'variables' as *;
3
- @forward 'variables';
4
- @forward 'functions';
5
- @forward 'mixins' show
6
- typography,
7
- state-layer,
8
- elevation,
9
- motion-transition,
10
- motion-exit,
11
- motion-enter,
12
- focus-ring,
13
- interactive-states,
14
- flex-center,
15
- center-content,
16
- container,
17
- truncate,
18
- shape,
19
- breakpoint-up,
20
- breakpoint-down,
21
- breakpoint-between,
22
- visually-hidden,
23
- reduced-motion,
24
- high-contrast,
25
- rtl,
26
- touch-target,
27
- custom-scrollbar,
28
- print;
@@ -1,4 +0,0 @@
1
- // Tokens on the base stylesheet: shape, the two typefaces, and the three
2
- // body-medium typescale tokens the body rule reads. The rest of the
3
- // typescale is material/styles/typography.
4
- @use "tokens" with ($typescale-tokens: "body");
@@ -1,9 +0,0 @@
1
- // Every typescale token, so material/styles/typography restores the scale on its
2
- // own. body-medium's font, size and line-height are also on the base, which
3
- // the body rule reads; the values match. Not imported by the full stylesheet:
4
- // base/tokens already emits every role there, once.
5
- @use "typescale-tokens" as scale;
6
-
7
- :root {
8
- @include scale.tokens("all");
9
- }