material 3.0.0-next.0 → 3.0.0-next.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 (245) hide show
  1. package/README.md +55 -370
  2. package/dist/components/badge/index.d.ts +1 -1
  3. package/dist/components/badge/index.js +1 -1
  4. package/dist/components/button/index.d.ts +1 -1
  5. package/dist/components/button/index.js +1 -1
  6. package/dist/components/card/index.d.ts +1 -1
  7. package/dist/components/card/index.js +1 -1
  8. package/dist/components/checkbox/index.d.ts +1 -1
  9. package/dist/components/checkbox/index.js +1 -1
  10. package/dist/components/chips/index.d.ts +1 -1
  11. package/dist/components/chips/index.js +1 -1
  12. package/dist/components/datepicker/index.d.ts +1 -1
  13. package/dist/components/datepicker/index.js +1 -1
  14. package/dist/components/dialog/index.d.ts +1 -1
  15. package/dist/components/dialog/index.js +1 -1
  16. package/dist/components/divider/index.d.ts +1 -1
  17. package/dist/components/divider/index.js +1 -1
  18. package/dist/components/drawer/index.d.ts +1 -1
  19. package/dist/components/drawer/index.js +1 -1
  20. package/dist/components/list/index.d.ts +1 -1
  21. package/dist/components/list/index.js +1 -1
  22. package/dist/components/list/list.d.ts +13 -0
  23. package/dist/components/list/types.d.ts +14 -1
  24. package/dist/components/loading-indicator/index.d.ts +1 -1
  25. package/dist/components/loading-indicator/index.js +1 -1
  26. package/dist/components/menu/index.d.ts +1 -1
  27. package/dist/components/menu/index.js +1 -1
  28. package/dist/components/progress/index.d.ts +1 -1
  29. package/dist/components/progress/index.js +1 -1
  30. package/dist/components/progress/types.d.ts +20 -10
  31. package/dist/components/radios/index.d.ts +1 -1
  32. package/dist/components/radios/index.js +1 -1
  33. package/dist/components/search/index.d.ts +1 -1
  34. package/dist/components/search/index.js +1 -1
  35. package/dist/components/select/index.d.ts +1 -1
  36. package/dist/components/select/index.js +1 -1
  37. package/dist/components/slider/index.d.ts +1 -1
  38. package/dist/components/slider/index.js +1 -1
  39. package/dist/components/slider/types.d.ts +7 -0
  40. package/dist/components/snackbar/index.d.ts +1 -1
  41. package/dist/components/snackbar/index.js +1 -1
  42. package/dist/components/split-button/index.d.ts +1 -1
  43. package/dist/components/split-button/index.js +1 -1
  44. package/dist/components/switch/index.d.ts +1 -1
  45. package/dist/components/switch/index.js +1 -1
  46. package/dist/components/tabs/index.d.ts +1 -0
  47. package/dist/components/tabs/index.js +1 -0
  48. package/dist/components/tabs/types.d.ts +15 -3
  49. package/dist/components/text-field/features/placement.js +7 -4
  50. package/dist/components/timepicker/index.d.ts +1 -1
  51. package/dist/components/timepicker/index.js +1 -1
  52. package/dist/components/tooltip/index.d.ts +1 -1
  53. package/dist/components/tooltip/index.js +1 -1
  54. package/dist/core/compose/features/textinput.js +3 -1
  55. package/dist/core/compose/index.d.ts +1 -1
  56. package/dist/core/dom/html.d.ts +1 -1
  57. package/dist/elements/css/button.css +1 -1
  58. package/dist/elements/css/button.js +1 -1
  59. package/dist/elements/css/card.css +1 -1
  60. package/dist/elements/css/card.js +1 -1
  61. package/dist/elements/css/checkbox.css +1 -1
  62. package/dist/elements/css/checkbox.js +1 -1
  63. package/dist/elements/css/chips.css +1 -1
  64. package/dist/elements/css/chips.js +1 -1
  65. package/dist/elements/css/dialog.css +1 -1
  66. package/dist/elements/css/dialog.js +1 -1
  67. package/dist/elements/css/extended-fab.css +1 -1
  68. package/dist/elements/css/extended-fab.js +1 -1
  69. package/dist/elements/css/fab-menu.css +1 -1
  70. package/dist/elements/css/fab-menu.js +1 -1
  71. package/dist/elements/css/fab.css +1 -1
  72. package/dist/elements/css/fab.js +1 -1
  73. package/dist/elements/css/hosts/switch.css +1 -1
  74. package/dist/elements/css/hosts/text-field.css +1 -1
  75. package/dist/elements/css/icon-button.css +1 -1
  76. package/dist/elements/css/icon-button.js +1 -1
  77. package/dist/elements/css/list.css +1 -1
  78. package/dist/elements/css/list.js +1 -1
  79. package/dist/elements/css/menu.css +1 -1
  80. package/dist/elements/css/menu.js +1 -1
  81. package/dist/elements/css/radios.css +1 -1
  82. package/dist/elements/css/radios.js +1 -1
  83. package/dist/elements/css/select.css +1 -1
  84. package/dist/elements/css/select.js +1 -1
  85. package/dist/elements/css/side-sheet.css +1 -1
  86. package/dist/elements/css/side-sheet.js +1 -1
  87. package/dist/elements/css/slider.css +1 -1
  88. package/dist/elements/css/slider.js +1 -1
  89. package/dist/elements/css/snackbar.css +1 -1
  90. package/dist/elements/css/snackbar.js +1 -1
  91. package/dist/elements/css/switch.css +1 -1
  92. package/dist/elements/css/switch.js +1 -1
  93. package/dist/elements/css/text-field.css +1 -1
  94. package/dist/elements/css/text-field.js +1 -1
  95. package/dist/elements/define.d.ts +20 -0
  96. package/dist/elements/preupgrade/badge.css +1 -1
  97. package/dist/elements/preupgrade/bottom-app-bar.css +1 -1
  98. package/dist/elements/preupgrade/bottom-sheet.css +1 -1
  99. package/dist/elements/preupgrade/button-group.css +1 -1
  100. package/dist/elements/preupgrade/button.css +2 -2
  101. package/dist/elements/preupgrade/card.css +1 -1
  102. package/dist/elements/preupgrade/carousel.css +1 -1
  103. package/dist/elements/preupgrade/checkbox.css +2 -2
  104. package/dist/elements/preupgrade/chips.css +1 -1
  105. package/dist/elements/preupgrade/datepicker.css +1 -1
  106. package/dist/elements/preupgrade/dialog.css +1 -1
  107. package/dist/elements/preupgrade/divider.css +1 -1
  108. package/dist/elements/preupgrade/drawer.css +1 -1
  109. package/dist/elements/preupgrade/extended-fab.css +1 -1
  110. package/dist/elements/preupgrade/fab-menu.css +1 -1
  111. package/dist/elements/preupgrade/fab.css +1 -1
  112. package/dist/elements/preupgrade/icon-button.css +1 -1
  113. package/dist/elements/preupgrade/list.css +2 -2
  114. package/dist/elements/preupgrade/loading-indicator.css +1 -1
  115. package/dist/elements/preupgrade/menu.css +1 -1
  116. package/dist/elements/preupgrade/navigation-bar.css +1 -1
  117. package/dist/elements/preupgrade/navigation-rail.css +1 -1
  118. package/dist/elements/preupgrade/progress.css +1 -1
  119. package/dist/elements/preupgrade/radios.css +2 -2
  120. package/dist/elements/preupgrade/search.css +1 -1
  121. package/dist/elements/preupgrade/select.css +1 -1
  122. package/dist/elements/preupgrade/side-sheet.css +1 -1
  123. package/dist/elements/preupgrade/slider.css +1 -1
  124. package/dist/elements/preupgrade/snackbar.css +1 -1
  125. package/dist/elements/preupgrade/split-button.css +1 -1
  126. package/dist/elements/preupgrade/switch.css +2 -2
  127. package/dist/elements/preupgrade/tabs.css +1 -1
  128. package/dist/elements/preupgrade/text-field.css +2 -2
  129. package/dist/elements/preupgrade/timepicker.css +1 -1
  130. package/dist/elements/preupgrade/toolbar.css +1 -1
  131. package/dist/elements/preupgrade/tooltip.css +1 -1
  132. package/dist/elements/preupgrade/top-app-bar.css +1 -1
  133. package/dist/elements/preupgrade.css +2 -2
  134. package/dist/elements/preupgrade.js +1 -1
  135. package/dist/elements/styles.d.ts +13 -1
  136. package/dist/elements/switch.d.ts +1 -0
  137. package/dist/elements/switch.js +1 -0
  138. package/dist/elements/text-field.js +1 -5
  139. package/dist/package.json +28 -4
  140. package/dist/styles/badge.css +1 -1
  141. package/dist/styles/base.css +1 -1
  142. package/dist/styles/bottom-app-bar.css +1 -1
  143. package/dist/styles/bottom-sheet.css +1 -1
  144. package/dist/styles/button-group.css +1 -1
  145. package/dist/styles/button.css +2 -2
  146. package/dist/styles/card.css +2 -2
  147. package/dist/styles/carousel.css +1 -1
  148. package/dist/styles/checkbox.css +2 -2
  149. package/dist/styles/chips.css +2 -2
  150. package/dist/styles/contrast.css +1 -1
  151. package/dist/styles/datepicker.css +1 -1
  152. package/dist/styles/dialog.css +2 -2
  153. package/dist/styles/divider.css +1 -1
  154. package/dist/styles/drawer.css +1 -1
  155. package/dist/styles/extended-fab.css +2 -2
  156. package/dist/styles/fab-menu.css +2 -2
  157. package/dist/styles/fab.css +2 -2
  158. package/dist/styles/icon-button.css +2 -2
  159. package/dist/styles/list.css +2 -2
  160. package/dist/styles/loading-indicator.css +1 -1
  161. package/dist/styles/menu.css +2 -2
  162. package/dist/styles/navigation-bar.css +1 -1
  163. package/dist/styles/navigation-rail.css +1 -1
  164. package/dist/styles/progress.css +1 -1
  165. package/dist/styles/radios.css +2 -2
  166. package/dist/styles/search.css +1 -1
  167. package/dist/styles/select.css +2 -2
  168. package/dist/styles/side-sheet.css +2 -2
  169. package/dist/styles/slider.css +2 -2
  170. package/dist/styles/snackbar.css +2 -2
  171. package/dist/styles/split-button.css +1 -1
  172. package/dist/styles/switch.css +2 -2
  173. package/dist/styles/tabs.css +1 -1
  174. package/dist/styles/text-field.css +2 -2
  175. package/dist/styles/timepicker.css +1 -1
  176. package/dist/styles/toolbar.css +1 -1
  177. package/dist/styles/tooltip.css +1 -1
  178. package/dist/styles/top-app-bar.css +1 -1
  179. package/dist/styles/typography.css +1 -1
  180. package/dist/styles/utilities.css +1 -1
  181. package/dist/styles.css +2 -2
  182. package/dist/themes/autumn-contrast.css +1 -1
  183. package/dist/themes/autumn.css +1 -1
  184. package/dist/themes/baseline-contrast.css +1 -1
  185. package/dist/themes/baseline.css +1 -1
  186. package/dist/themes/brownbeige-contrast.css +1 -1
  187. package/dist/themes/brownbeige.css +1 -1
  188. package/dist/themes/content-contrast.css +1 -1
  189. package/dist/themes/content.css +1 -1
  190. package/dist/themes/desert-contrast.css +1 -1
  191. package/dist/themes/desert.css +1 -1
  192. package/dist/themes/expressive-contrast.css +1 -1
  193. package/dist/themes/expressive.css +1 -1
  194. package/dist/themes/fidelity-contrast.css +1 -1
  195. package/dist/themes/fidelity.css +1 -1
  196. package/dist/themes/forest-contrast.css +1 -1
  197. package/dist/themes/forest.css +1 -1
  198. package/dist/themes/fruit-salad-contrast.css +1 -1
  199. package/dist/themes/fruit-salad.css +1 -1
  200. package/dist/themes/highcontrast-contrast.css +1 -1
  201. package/dist/themes/highcontrast.css +1 -1
  202. package/dist/themes/monochrome-contrast.css +1 -1
  203. package/dist/themes/monochrome.css +1 -1
  204. package/dist/themes/neutral-contrast.css +1 -1
  205. package/dist/themes/neutral.css +1 -1
  206. package/dist/themes/ocean-contrast.css +1 -1
  207. package/dist/themes/ocean.css +1 -1
  208. package/dist/themes/rainbow-contrast.css +1 -1
  209. package/dist/themes/rainbow.css +1 -1
  210. package/dist/themes/sageivory-contrast.css +1 -1
  211. package/dist/themes/sageivory.css +1 -1
  212. package/dist/themes/spring-contrast.css +1 -1
  213. package/dist/themes/spring.css +1 -1
  214. package/dist/themes/summer-contrast.css +1 -1
  215. package/dist/themes/summer.css +1 -1
  216. package/dist/themes/sunset-contrast.css +1 -1
  217. package/dist/themes/sunset.css +1 -1
  218. package/dist/themes/tealcaramel-contrast.css +1 -1
  219. package/dist/themes/tealcaramel.css +1 -1
  220. package/dist/themes/vibrant-contrast.css +1 -1
  221. package/dist/themes/vibrant.css +1 -1
  222. package/package.json +28 -4
  223. package/src/styles/abstract/_mixins.scss +17 -5
  224. package/src/styles/abstract/_variables.scss +1 -1
  225. package/src/styles/components/_button.scss +10 -7
  226. package/src/styles/components/_checkbox.scss +10 -0
  227. package/src/styles/components/_chips.scss +10 -0
  228. package/src/styles/components/_dialog.scss +16 -0
  229. package/src/styles/components/_icon-button.scss +6 -0
  230. package/src/styles/components/_list.scss +43 -2
  231. package/src/styles/components/_menu.scss +8 -0
  232. package/src/styles/components/_radios.scss +22 -4
  233. package/src/styles/components/_select.scss +13 -29
  234. package/src/styles/components/_side-sheet.scss +22 -0
  235. package/src/styles/components/_slider.scss +3 -3
  236. package/src/styles/components/_switch.scss +19 -0
  237. package/src/styles/components/_text-field.scss +87 -321
  238. package/src/styles/elements/_button.scss +17 -1
  239. package/src/styles/elements/_checkbox.scss +16 -0
  240. package/src/styles/elements/_list.scss +6 -0
  241. package/src/styles/elements/_radios.scss +3 -2
  242. package/src/styles/elements/_switch.scss +52 -0
  243. package/src/styles/elements/_text-field.scss +21 -0
  244. package/dist/LICENSE +0 -21
  245. package/dist/README.md +0 -438
@@ -8,9 +8,10 @@
8
8
  $component: "#{base.$prefix}-select";
9
9
 
10
10
  .#{$component} {
11
- // Base styles - building on text field base
11
+ // Base styles - building on text field base. No width of its own: unsized,
12
+ // a select is the text field's 280px, as <m-select> is; it took 100% of
13
+ // its container, which the text field never did.
12
14
  position: relative;
13
- width: 100%;
14
15
  cursor: pointer;
15
16
 
16
17
  // Menu when it's a direct child of select (container mode)
@@ -22,6 +23,10 @@ $component: "#{base.$prefix}-select";
22
23
  right: 0;
23
24
  z-index: 1;
24
25
  margin-top: 0;
26
+ // The field's width, as in the top layer (Compose
27
+ // exposedDropdownSize(matchAnchorWidth = true)): the menu's own 280px
28
+ // maximum left it short of a wider field. Its 112px minimum stays.
29
+ max-width: none;
25
30
  }
26
31
 
27
32
  // Transition
@@ -125,33 +130,12 @@ $component: "#{base.$prefix}-select";
125
130
 
126
131
  .#{base.$prefix}-menu__item {
127
132
  min-height: 3rem;
128
-
129
- // Selected state
130
- &--selected {
131
- background-color: t.alpha("primary", 0.12);
132
- color: t.color("primary");
133
- font-weight: 500;
134
-
135
- &::after {
136
- content: "";
137
- display: block;
138
- position: absolute;
139
- right: 12px;
140
- width: 18px;
141
- height: 18px;
142
- // Use mask-image instead of background-image
143
- mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
144
- -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
145
- mask-size: contain;
146
- -webkit-mask-size: contain;
147
- mask-repeat: no-repeat;
148
- -webkit-mask-repeat: no-repeat;
149
- mask-position: center;
150
- -webkit-mask-position: center;
151
- // Use currentColor to match the text color
152
- background-color: currentColor;
153
- }
154
- }
133
+ // The selected option is the menu's own, in every layer:
134
+ // secondary-container and on-secondary-container
135
+ // (md.comp.menu.list-item.selected.container.color and
136
+ // .label-text.color, m3.material.io), with the menu's mark. The
137
+ // rule that was here gave the top layer the primary colour at
138
+ // 12% and a second mark.
155
139
  }
156
140
  }
157
141
 
@@ -88,6 +88,12 @@ $component: "#{base.$prefix}-side-sheet";
88
88
 
89
89
  // 16dp on the icon side, per the specs' start padding with an icon
90
90
  &__close {
91
+ // The button is the layer's and the 48px target's containing block. That
92
+ // cannot come from the state layer's `:where()` rule alone: it adds no
93
+ // specificity, so a page reset like `button { position: static }` would
94
+ // win, and the layer and the target would anchor to the sheet's
95
+ // container instead.
96
+ position: relative;
91
97
  flex: 0 0 auto;
92
98
  display: inline-flex;
93
99
  align-items: center;
@@ -108,6 +114,22 @@ $component: "#{base.$prefix}-side-sheet";
108
114
  outline: 3px solid t.color("secondary");
109
115
  outline-offset: 2px;
110
116
  }
117
+
118
+ // FLO-579: the 40px button carries a 48px target, the icon button's own
119
+ // mechanism (its --xs/--s ::after): the box reaches 4px past each edge.
120
+ // The `position: relative` above is the button's own, so the box anchors
121
+ // to the button whatever the page does to buttons.
122
+ // m3.material.io, Density: "The default target size should be at least
123
+ // 48x48 CSS pixels".
124
+ &::after {
125
+ content: "";
126
+ position: absolute;
127
+ width: 48px;
128
+ height: 48px;
129
+ top: 50%;
130
+ left: 50%;
131
+ transform: translate(-50%, -50%);
132
+ }
111
133
  }
112
134
 
113
135
  &__content {
@@ -54,11 +54,11 @@ $component: '#{base.$prefix}-slider';
54
54
  outline: none;
55
55
  }
56
56
 
57
- // Label styles
57
+ // Label
58
+ // Body Large, as the checkbox, radio and switch labels (FLO-587).
58
59
  &__label {
59
60
  display: block;
60
- font-size: 18px;
61
- font-weight: 400;
61
+ @include m.typography('body-large');
62
62
  color: t.color('on-surface');
63
63
  margin-bottom: 4px;
64
64
  // labelPosition: 'end' puts it below the track.
@@ -29,6 +29,25 @@ $component: '#{base.$prefix}-switch';
29
29
  column-gap: 12px;
30
30
  }
31
31
 
32
+ // A switch with neither a label nor supporting text is its own target: no
33
+ // gap (the 12px belongs between text and the track, and there is none), so
34
+ // the root is the 52px track's width and 48px tall with the 32px track
35
+ // centred. M3 "Switch" -> Specs -> Measurements: Track 32x52dp and "Target:
36
+ // Size 48dp", with no height for a label row; its Accessibility section:
37
+ // "Don't apply density to switches by default — this lowers their targets
38
+ // below our best practice of 48x48 CSS pixels." So this row is 48 tall —
39
+ // the root's 4px above and below leave the container 40 — while a switch
40
+ // with a label, and one whose only text is its supporting text (`__helper`,
41
+ // which stands where the label would), keeps the 56px row and the gap.
42
+ // `:where` keeps this rule's weight level with `--dense`, which follows and
43
+ // so still wins: a switch that opts into the denser row keeps it.
44
+ &:where(:not(:has(.#{$component}__label, .#{$component}__helper))) {
45
+ .#{$component}__container {
46
+ column-gap: 0;
47
+ min-height: 40px;
48
+ }
49
+ }
50
+
32
51
  // Content wrapper. The gap is on the container, so it stays between the label
33
52
  // and the track whichever side the label is on, in either direction.
34
53
  &__content {
@@ -8,11 +8,18 @@
8
8
  // Define the component once
9
9
  $component: "#{base.$prefix}-text-field";
10
10
 
11
- // Where the text starts or ends beside a prefix or a suffix: the affix's own
12
- // inset, its width, which placement.ts measures into a custom property (32px
13
- // until it has), and the 2dp to the text (PrefixSuffixTextPadding).
14
- @function beside-affix($inset, $affix) {
15
- @return calc(#{$inset} + var(--#{$component}-#{$affix}-width, 32px) + 2px);
11
+ // Right to left (FLO-562). Every horizontal inset is a custom property, set
12
+ // once whatever the direction, and the rules in this mixin, at the end of the
13
+ // component's block, are the whole mirror. Two selectors: an ancestor's `dir`,
14
+ // which needs no script, and --rtl, which placement.ts sets from the computed
15
+ // direction, for a field in a shadow root, where a `dir` outside it does not
16
+ // reach. Physical sides, as bundlers lower logical insets, corners and :dir()
17
+ // into :lang() lists that miss dir="rtl".
18
+ @mixin mirrored {
19
+ [dir='rtl'] &,
20
+ &.#{$component}--rtl {
21
+ @content;
22
+ }
16
23
  }
17
24
 
18
25
  // Autofill detection animations
@@ -60,7 +67,7 @@ $component: "#{base.$prefix}-text-field";
60
67
  @include m.typography("body-large");
61
68
  user-select: none;
62
69
  position: absolute;
63
- left: 16px;
70
+ left: var(--#{$component}-start, 16px);
64
71
  top: 50%;
65
72
  transform: translateY(-50%);
66
73
  transform-origin: left top;
@@ -136,7 +143,7 @@ $component: "#{base.$prefix}-text-field";
136
143
  &__prefix {
137
144
  @include m.typography("body-large");
138
145
  position: absolute;
139
- left: 16px;
146
+ left: var(--#{$component}-start, 16px);
140
147
  top: 50%;
141
148
  transform: translateY(-50%);
142
149
  color: t.color("on-surface-variant");
@@ -157,7 +164,7 @@ $component: "#{base.$prefix}-text-field";
157
164
  &__suffix {
158
165
  @include m.typography("body-large");
159
166
  position: absolute;
160
- right: 16px;
167
+ right: var(--#{$component}-end, 16px);
161
168
  top: 50%;
162
169
  transform: translateY(-50%);
163
170
  color: t.color("on-surface-variant");
@@ -219,59 +226,30 @@ $component: "#{base.$prefix}-text-field";
219
226
  }
220
227
  }
221
228
 
222
- // A field with a prefix or a suffix pads its input from --text-start and
223
- // --text-end (the rules are last in this block): what stands on that side,
224
- // an icon then the affix, each after the other (FLO-299). The label is
225
- // not moved by a prefix: it starts where the content does (Compose
226
- // TextFieldImpl, "Prefix/suffix does not get applied to label").
227
- &--with-prefix {
228
- --#{$component}-text-start: #{beside-affix(16px, prefix)};
229
- }
230
-
231
- &--with-suffix {
232
- --#{$component}-text-end: #{beside-affix(16px, suffix)};
233
- }
234
-
235
- // Adjustments when icons are present: an icon is 12dp in, and what
236
- // follows it 16dp further ("Left/right padding with icons 12dp", "Padding
237
- // between icons and text 16dp", m3.material.io text fields): 52dp with
238
- // the 24dp icon, 48dp with compact's 20dp one
229
+ // Where the content starts and ends: 16dp in (TextFieldPadding), or after
230
+ // an icon, which is 12dp in with 16dp after it ("Left/right padding with
231
+ // icons 12dp", "Padding between icons and text 16dp", m3.material.io text
232
+ // fields): 52dp with the 24dp icon, 48dp with compact's 20dp one. The
233
+ // label, a prefix and a suffix stand there; the label is not moved by a
234
+ // prefix (Compose TextFieldImpl, "Prefix/suffix does not get applied to
235
+ // label").
239
236
  &--with-leading-icon {
240
- --#{$component}-text-start: 52px;
241
-
242
- .#{$component}__label {
243
- left: 52px;
244
- }
245
-
246
- .#{$component}__input {
247
- padding-left: 52px;
248
- }
249
-
250
- // With a prefix too: the icon, the prefix, then the text
251
- &.#{$component}--with-prefix {
252
- --#{$component}-text-start: #{beside-affix(52px, prefix)};
253
-
254
- .#{$component}__prefix {
255
- left: 52px;
256
- }
257
- }
237
+ --#{$component}-start: 52px;
258
238
  }
259
239
 
260
240
  &--with-trailing-icon {
261
- --#{$component}-text-end: 52px;
262
-
263
- .#{$component}__input {
264
- padding-right: 52px;
265
- }
241
+ --#{$component}-end: 52px;
242
+ }
266
243
 
267
- // With a suffix too: the text, the suffix, then the icon
268
- &.#{$component}--with-suffix {
269
- --#{$component}-text-end: #{beside-affix(52px, suffix)};
244
+ // What a prefix or a suffix adds before the text: its width, which
245
+ // placement.ts measures into a custom property (32px until it has), and
246
+ // the 2dp to the text (PrefixSuffixTextPadding) (FLO-299)
247
+ &--with-prefix {
248
+ --#{$component}-prefix-space: calc(var(--#{$component}-prefix-width, 32px) + 2px);
249
+ }
270
250
 
271
- .#{$component}__suffix {
272
- right: 52px;
273
- }
274
- }
251
+ &--with-suffix {
252
+ --#{$component}-suffix-space: calc(var(--#{$component}-suffix-width, 32px) + 2px);
275
253
  }
276
254
 
277
255
  // Error state
@@ -399,68 +377,6 @@ $component: "#{base.$prefix}-text-field";
399
377
  }
400
378
  }
401
379
 
402
- // RTL support
403
- @include m.rtl {
404
- &__label {
405
- left: auto;
406
- right: 16px;
407
- transform-origin: right top;
408
- }
409
-
410
- &__prefix {
411
- left: auto;
412
- right: 16px;
413
- }
414
-
415
- &__suffix {
416
- right: auto;
417
- left: 16px;
418
- }
419
-
420
- &__leading-icon {
421
- left: auto;
422
- right: 12px;
423
- }
424
-
425
- &__trailing-icon {
426
- right: auto;
427
- left: 12px;
428
- }
429
-
430
- &--with-leading-icon {
431
- .#{$component}__label {
432
- left: auto;
433
- right: 52px;
434
- }
435
-
436
- .#{$component}__input {
437
- padding-left: 16px;
438
- padding-right: 52px;
439
- }
440
-
441
- &.#{$component}--with-prefix {
442
- .#{$component}__prefix {
443
- left: auto;
444
- right: 52px;
445
- }
446
- }
447
- }
448
-
449
- &--with-trailing-icon {
450
- .#{$component}__input {
451
- padding-right: 16px;
452
- padding-left: 52px;
453
- }
454
-
455
- &.#{$component}--with-suffix {
456
- .#{$component}__suffix {
457
- right: auto;
458
- left: 52px;
459
- }
460
- }
461
- }
462
- }
463
-
464
380
  // ===== FILLED VARIANT =====
465
381
  &--filled {
466
382
  // the label at rest is on-surface-variant at full strength: faded to
@@ -599,57 +515,9 @@ $component: "#{base.$prefix}-text-field";
599
515
  }
600
516
 
601
517
  // Icon adjustments for filled variant
602
- &.#{$component}--with-leading-icon {
603
- .#{$component}__input {
604
- padding-left: 52px;
605
- }
606
-
607
- .#{$component}__label {
608
- left: 52px;
609
- }
610
-
611
- .#{$component}__leading-icon {
612
- top: 28px;
613
- }
614
- }
615
-
616
- &.#{$component}--with-trailing-icon {
617
- .#{$component}__input {
618
- padding-right: 52px;
619
- }
620
-
621
- .#{$component}__trailing-icon {
622
- top: 28px;
623
- }
624
- }
625
-
626
- // RTL support
627
- @include m.rtl {
628
- .#{$component}__label {
629
- left: auto;
630
- right: 16px;
631
- }
632
-
633
- &.#{$component}--with-leading-icon {
634
- .#{$component}__input {
635
- // The sides only: the shorthand also set the default density's
636
- // top and bottom on a compact field
637
- padding-left: 16px;
638
- padding-right: 52px;
639
- }
640
-
641
- .#{$component}__label {
642
- left: auto;
643
- right: 52px;
644
- }
645
- }
646
-
647
- &.#{$component}--with-trailing-icon {
648
- .#{$component}__input {
649
- padding-right: 16px;
650
- padding-left: 52px;
651
- }
652
- }
518
+ &.#{$component}--with-leading-icon .#{$component}__leading-icon,
519
+ &.#{$component}--with-trailing-icon .#{$component}__trailing-icon {
520
+ top: 28px;
653
521
  }
654
522
  }
655
523
 
@@ -742,7 +610,6 @@ $component: "#{base.$prefix}-text-field";
742
610
 
743
611
  // LabelColor at full strength: faded to 0.5 it failed 4.5:1 (FLO-298)
744
612
  .#{$component}__label {
745
- left: 16px;
746
613
  top: 50%;
747
614
  }
748
615
 
@@ -753,8 +620,8 @@ $component: "#{base.$prefix}-text-field";
753
620
  // its height: up the 28px to the edge, and half its scaled box
754
621
  transform: translateY(calc(-28px - 37.5%)) scale(0.75);
755
622
  // The floated label starts 16dp in, inside the notch, whatever
756
- // the icon or prefix at rest
757
- left: 16px;
623
+ // the icon at rest: the label's own inset, either direction
624
+ --#{$component}-start: 16px;
758
625
  }
759
626
 
760
627
  // Floated from the input's own state too, as the filled variant is
@@ -762,7 +629,7 @@ $component: "#{base.$prefix}-text-field";
762
629
  // Centred on the top edge (`endY = -(it.height / 2)`), whatever
763
630
  // its height: up the 28px to the edge, and half its scaled box
764
631
  transform: translateY(calc(-28px - 37.5%)) scale(0.75);
765
- left: 16px;
632
+ --#{$component}-start: 16px;
766
633
  }
767
634
 
768
635
  // Hover state
@@ -810,78 +677,6 @@ $component: "#{base.$prefix}-text-field";
810
677
  pointer-events: none;
811
678
  }
812
679
 
813
- // Icon adjustments for outlined variant
814
- &.#{$component}--with-leading-icon {
815
- .#{$component}__input {
816
- padding-left: 52px;
817
- }
818
-
819
- .#{$component}__label {
820
- left: 52px;
821
- }
822
-
823
- &:not(.#{$component}--empty) .#{$component}__label,
824
- &.#{$component}--focused .#{$component}__label {
825
- left: 16px;
826
- }
827
- }
828
-
829
- &.#{$component}--with-trailing-icon {
830
- .#{$component}__input {
831
- padding-right: 52px;
832
- }
833
- }
834
-
835
- // Right to left follows --rtl, which placement.ts sets from the
836
- // computed direction: the [dir] selectors cannot see a direction set
837
- // outside a shadow root, and bundlers lower logical insets, corners
838
- // and :dir() into :lang() lists that miss dir="rtl"
839
- &.#{$component}--rtl {
840
- .#{$component}__label {
841
- left: auto;
842
- right: 16px;
843
- transform-origin: right top;
844
- }
845
-
846
- &.#{$component}--with-leading-icon .#{$component}__label {
847
- left: auto;
848
- right: 52px;
849
- }
850
-
851
- &:not(.#{$component}--empty) .#{$component}__label,
852
- &.#{$component}--focused .#{$component}__label,
853
- &:has(.#{$component}__input:is(:not(:placeholder-shown), :autofill, :-webkit-autofill)) .#{$component}__label {
854
- left: auto;
855
- right: 16px;
856
- }
857
-
858
- .#{$component}__outline-leading {
859
- border-radius: 0 f.get-shape("extra-small")
860
- f.get-shape("extra-small") 0;
861
- }
862
-
863
- .#{$component}__outline-trailing {
864
- border-radius: f.get-shape("extra-small") 0 0
865
- f.get-shape("extra-small");
866
- }
867
- }
868
-
869
- // RTL support for the light DOM
870
- @include m.rtl {
871
- &.#{$component}--with-leading-icon {
872
- .#{$component}__input {
873
- padding-left: 16px;
874
- padding-right: 52px;
875
- }
876
- }
877
-
878
- &.#{$component}--with-trailing-icon {
879
- .#{$component}__input {
880
- padding-right: 16px;
881
- padding-left: 52px;
882
- }
883
- }
884
- }
885
680
  }
886
681
 
887
682
  // Multiline styles
@@ -1037,98 +832,66 @@ $component: "#{base.$prefix}-text-field";
1037
832
  }
1038
833
  }
1039
834
 
1040
- // Adjust element positions for compact with icons
835
+ // The compact icon box is 20dp: the content starts 48dp in
1041
836
  &.#{$component}--with-leading-icon {
1042
- --#{$component}-text-start: 48px;
1043
-
1044
- .#{$component}__label {
1045
- left: 48px;
1046
- }
1047
-
1048
- .#{$component}__input {
1049
- padding-left: 48px;
1050
- }
1051
-
1052
- &.#{$component}--with-prefix {
1053
- --#{$component}-text-start: #{beside-affix(48px, prefix)};
1054
-
1055
- .#{$component}__prefix {
1056
- left: 48px;
1057
- }
1058
- }
837
+ --#{$component}-start: 48px;
1059
838
  }
1060
839
 
1061
840
  &.#{$component}--with-trailing-icon {
1062
- --#{$component}-text-end: 48px;
1063
-
1064
- .#{$component}__input {
1065
- padding-right: 48px;
1066
- }
841
+ --#{$component}-end: 48px;
842
+ }
843
+ }
1067
844
 
1068
- &.#{$component}--with-suffix {
1069
- --#{$component}-text-end: #{beside-affix(48px, suffix)};
845
+ // ===== THE INPUT'S SIDES, AND THE MIRROR =====
846
+ // The text starts where the content does, after a prefix if there is one,
847
+ // and ends before a suffix. Last, and one class heavier (the field), so it
848
+ // holds over the variants' and the densities' padding shorthands.
849
+ .#{$component}__field .#{$component}__input {
850
+ padding-left: calc(var(--#{$component}-start, 16px) + var(--#{$component}-prefix-space, 0px));
851
+ padding-right: calc(var(--#{$component}-end, 16px) + var(--#{$component}-suffix-space, 0px));
852
+ }
1070
853
 
1071
- .#{$component}__suffix {
1072
- right: 48px;
1073
- }
1074
- }
854
+ @include mirrored {
855
+ .#{$component}__label {
856
+ left: auto;
857
+ right: var(--#{$component}-start, 16px);
858
+ transform-origin: right top;
1075
859
  }
1076
860
 
1077
- // RTL adjustments for compact density
1078
- @include m.rtl {
1079
- &.#{$component}--with-leading-icon {
1080
- .#{$component}__label {
1081
- left: auto;
1082
- right: 48px;
1083
- }
861
+ .#{$component}__prefix {
862
+ left: auto;
863
+ right: var(--#{$component}-start, 16px);
864
+ }
1084
865
 
1085
- .#{$component}__input {
1086
- padding-left: 16px;
1087
- padding-right: 48px;
1088
- }
866
+ .#{$component}__suffix {
867
+ right: auto;
868
+ left: var(--#{$component}-end, 16px);
869
+ }
1089
870
 
1090
- &.#{$component}--with-prefix {
1091
- .#{$component}__prefix {
1092
- left: auto;
1093
- right: 48px;
1094
- }
1095
- }
1096
- }
871
+ .#{$component}__leading-icon {
872
+ left: auto;
873
+ right: 12px;
874
+ }
1097
875
 
1098
- &.#{$component}--with-trailing-icon {
1099
- .#{$component}__input {
1100
- padding-right: 16px;
1101
- padding-left: 48px;
1102
- }
876
+ .#{$component}__trailing-icon {
877
+ right: auto;
878
+ left: 12px;
879
+ }
1103
880
 
1104
- &.#{$component}--with-suffix {
1105
- .#{$component}__suffix {
1106
- right: auto;
1107
- left: 48px;
1108
- }
1109
- }
1110
- }
881
+ .#{$component}__field .#{$component}__input {
882
+ padding-left: calc(var(--#{$component}-end, 16px) + var(--#{$component}-suffix-space, 0px));
883
+ padding-right: calc(var(--#{$component}-start, 16px) + var(--#{$component}-prefix-space, 0px));
1111
884
  }
1112
- }
1113
885
 
1114
- // ===== BESIDE A PREFIX OR A SUFFIX =====
1115
- // The input's padding in a field with a prefix or a suffix, from the two
1116
- // insets set above. Last, and one class heavier, so it holds over the
1117
- // variants' and the densities' paddings. A selector list, not :is():
1118
- // bundlers emit an :is() rule three times, with the -webkit-any() and
1119
- // -moz-any() forms.
1120
- &.#{$component}--with-prefix,
1121
- &.#{$component}--with-suffix {
1122
- .#{$component}__input {
1123
- padding-left: var(--#{$component}-text-start, 16px);
1124
- padding-right: var(--#{$component}-text-end, 16px);
886
+ // The outline's corners follow its segments
887
+ .#{$component}__outline-leading {
888
+ border-radius: 0 f.get-shape("extra-small")
889
+ f.get-shape("extra-small") 0;
1125
890
  }
1126
891
 
1127
- @include m.rtl {
1128
- .#{$component}__input {
1129
- padding-left: var(--#{$component}-text-end, 16px);
1130
- padding-right: var(--#{$component}-text-start, 16px);
1131
- }
892
+ .#{$component}__outline-trailing {
893
+ border-radius: f.get-shape("extra-small") 0 0
894
+ f.get-shape("extra-small");
1132
895
  }
1133
896
  }
1134
897
  }
@@ -1184,7 +947,10 @@ $component: "#{base.$prefix}-text-field";
1184
947
  cursor: default;
1185
948
  }
1186
949
 
1187
- @include m.rtl {
950
+ // The field's mirror, for the button: an ancestor's `dir`, or the
951
+ // field's --rtl inside a shadow root (FLO-562)
952
+ [dir='rtl'] &,
953
+ .#{$component}--rtl & {
1188
954
  right: auto;
1189
955
  left: 4px;
1190
956
  }