mtrl 0.5.3 → 0.5.5

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.
@@ -10,1015 +10,1026 @@ $component: "#{base.$prefix}-textfield";
10
10
 
11
11
  // Autofill detection animations
12
12
  @keyframes onAutoFillStart {
13
- from {
14
- opacity: 1;
15
- }
16
- to {
17
- opacity: 1;
18
- }
13
+ from {
14
+ opacity: 1;
15
+ }
16
+ to {
17
+ opacity: 1;
18
+ }
19
19
  }
20
20
 
21
21
  @keyframes onAutoFillCancel {
22
- from {
23
- opacity: 1;
24
- }
25
- to {
26
- opacity: 1;
27
- }
22
+ from {
23
+ opacity: 1;
24
+ }
25
+ to {
26
+ opacity: 1;
27
+ }
28
28
  }
29
29
 
30
30
  // ===== BASE STYLES =====
31
31
  .#{$component} {
32
- position: relative;
33
- display: inline-flex;
34
- flex-direction: column;
35
- min-width: 210px;
36
- // align-self: flex-start; // Prevents growing to fill the container's height
37
- flex: 0 0 auto; // Don't grow or shrink; keep natural size
38
- // Label
39
- &-label {
40
- @include m.typography("body-large");
41
- user-select: none;
42
- position: absolute;
43
- left: 16px;
44
- top: 50%;
45
- transform: translateY(-50%);
46
- transform-origin: left top;
47
- pointer-events: none;
48
- border-radius: 2px;
49
- color: t.color("on-surface-variant");
50
- transition: transform v.motion("duration-short4")
51
- v.motion("easing-emphasized"),
52
- color v.motion("duration-short2") v.motion("easing-standard"),
53
- left v.motion("duration-short4") v.motion("easing-emphasized");
54
- }
55
-
56
- // Input element
57
- &-input {
58
- @include m.typography("body-large");
59
- @include m.shape("extra-small");
60
- padding: 13px 16px;
61
- width: 100%;
62
- height: 56px;
63
- color: t.color("on-surface");
64
- border: 0;
65
- appearance: none;
66
- outline: none;
67
-
68
- // Animation to detect autofill
69
- animation-name: onAutoFillCancel;
70
- animation-duration: 10ms;
71
-
72
- // Transition to help detect autofill changes
73
- transition: background-color 0s ease-out 50000000s;
74
-
75
- &::placeholder {
76
- color: transparent;
77
- }
78
-
79
- // Autofill styles
80
- &:-webkit-autofill {
81
- animation-name: onAutoFillStart;
82
- animation-duration: 10ms;
83
- -webkit-text-fill-color: t.color("on-surface");
84
- transition: background-color 5000s ease-in-out 0s; // Long transition to keep the background
85
-
86
- & ~ .#{$component}-label {
87
- transform: translateY(-95%) scale(0.75);
88
- background-color: t.color("surface");
89
- }
90
- }
91
-
92
- // Firefox autofill
93
- &:autofill {
94
- color: t.color("on-surface");
95
-
96
- & ~ .#{$component}-label {
97
- transform: translateY(-95%) scale(0.75);
98
- background-color: t.color("surface");
99
- }
100
- }
101
-
102
- // Non-empty input should also float the label
103
- &:not(:placeholder-shown) {
104
- & ~ .#{$component}-label {
105
- transform: translateY(-95%) scale(0.75);
106
- }
107
- }
108
- }
109
-
110
- // Prefix text
111
- &-prefix {
112
- @include m.typography("body-large");
113
- position: absolute;
114
- left: 12px;
115
- top: 50%;
116
- transform: translateY(-50%);
117
- color: t.color("on-surface");
118
- pointer-events: none;
119
- z-index: 2; // Increased to ensure it stays above input
120
- white-space: nowrap; // Prevent text wrapping
121
- max-width: 40%; // Prevent extreme overflow
122
- overflow: hidden;
123
- text-overflow: ellipsis;
124
- transition: top v.motion("duration-short4") v.motion("easing-emphasized"); // Add transition for top position
125
- }
126
-
127
- // Suffix text
128
- &-suffix {
129
- @include m.typography("body-large");
130
- position: absolute;
131
- right: 16px;
132
- top: 50%;
133
- transform: translateY(-50%);
134
- color: t.color("on-surface");
135
- pointer-events: none;
136
- z-index: 2; // Increased to ensure it stays above input
137
- white-space: nowrap; // Prevent text wrapping
138
- max-width: 40%; // Prevent extreme overflow
139
- overflow: hidden;
140
- text-overflow: ellipsis;
141
- transition: top v.motion("duration-short4") v.motion("easing-emphasized"); // Add transition for top position
142
- }
143
-
144
- // Leading icon
145
- &-leading-icon {
146
- opacity: 0.85;
147
- position: absolute;
148
- left: 12px;
149
- top: 50%;
150
- transform: translateY(-50%);
151
- display: flex;
152
- align-items: center;
153
- justify-content: center;
154
- width: 24px;
155
- height: 24px;
156
- pointer-events: none;
157
- color: t.color("on-surface-variant");
158
- z-index: 1;
159
- transition: top v.motion("duration-short4") v.motion("easing-emphasized"); // Add transition for top position
160
-
161
- svg {
162
- width: 20px;
163
- height: 20px;
164
- }
165
- }
166
-
167
- // Trailing icon
168
- &-trailing-icon {
169
- opacity: 0.85;
170
- position: absolute;
171
- right: 12px;
172
- top: 50%;
173
- transform: translateY(-50%);
174
- display: flex;
175
- align-items: center;
176
- justify-content: center;
177
- width: 24px;
178
- height: 24px;
179
- color: t.color("on-surface-variant");
180
- z-index: 1;
181
- cursor: pointer;
182
- transition: top v.motion("duration-short4") v.motion("easing-emphasized"); // Add transition for top position
183
-
184
- svg {
185
- width: 20px;
186
- height: 20px;
187
- }
188
- }
189
-
190
- // Adjustments when prefix/suffix are present - base case styling
191
- // JavaScript will handle dynamic sizing, these are fallbacks
192
- &--with-prefix {
193
- .#{$component}-label {
194
- // Default value - will be overridden by JS for precise positioning
195
- left: 48px;
196
- }
197
-
198
- .#{$component}-input {
199
- // Default value - will be overridden by JS for precise padding
200
- padding-left: 48px;
201
- }
202
- }
203
-
204
- &--with-suffix {
205
- .#{$component}-input {
206
- // Default value - will be overridden by JS for precise padding
207
- padding-right: 48px;
208
- }
209
- }
210
-
211
- // Adjustments when icons are present
212
- &--with-leading-icon {
213
- .#{$component}-label {
214
- left: 44px;
215
- }
216
-
217
- .#{$component}-input {
218
- padding-left: 44px;
219
- }
220
-
221
- // If there's also a prefix, adjust positions
222
- &.#{$component}--with-prefix {
223
- .#{$component}-prefix {
224
- left: 44px;
225
- }
226
-
227
- .#{$component}-label {
228
- // Default value - will be overridden by JS for precise positioning
229
- left: 76px;
230
- }
231
-
232
- .#{$component}-input {
233
- // Default value - will be overridden by JS for precise padding
234
- padding-left: 76px;
235
- }
236
- }
237
- }
238
-
239
- &--with-trailing-icon {
240
- .#{$component}-input {
241
- padding-right: 44px;
242
- }
243
-
244
- // If there's also a suffix, adjust positions
245
- &.#{$component}--with-suffix {
246
- .#{$component}-suffix {
247
- right: 44px;
248
- }
249
-
250
- .#{$component}-input {
251
- // Default value - will be overridden by JS for precise padding
252
- padding-right: 76px;
253
- }
254
- }
255
- }
256
-
257
- // Error state
258
- &--error {
259
- border-color: t.color("error");
260
-
261
- .#{$component}-label {
262
- color: t.color("error");
263
- }
264
-
265
- .#{$component}-leading-icon,
266
- .#{$component}-trailing-icon,
267
- .#{$component}-prefix,
268
- .#{$component}-suffix {
269
- color: t.color("error");
270
- }
271
- }
272
-
273
- // Disabled state
274
- &--disabled {
275
- .#{$component}-input {
276
- opacity: 0.38;
277
- border-color: t.color("on-surface");
278
- background-color: t.alpha("on-surface", 0.04);
279
- pointer-events: none;
280
- }
281
-
282
- .#{$component}-label {
283
- color: t.color("on-surface");
284
- opacity: 0.38;
285
- }
286
-
287
- .#{$component}-leading-icon,
288
- .#{$component}-trailing-icon,
289
- .#{$component}-prefix,
290
- .#{$component}-suffix {
291
- color: t.color("on-surface");
292
- opacity: 0.38;
293
- }
294
- }
295
-
296
- // Disabled state - legacy support for direct input disabled
297
- &-input:disabled {
298
- opacity: 0.38;
299
- border-color: t.color("on-surface");
300
- background-color: t.alpha("on-surface", 0.04);
301
- pointer-events: none;
302
-
303
- & ~ .#{$component}-label,
304
- & ~ .#{$component}-leading-icon,
305
- & ~ .#{$component}-trailing-icon,
306
- & ~ .#{$component}-prefix,
307
- & ~ .#{$component}-suffix {
308
- color: t.color("on-surface");
309
- opacity: 0.38;
310
- }
311
- }
312
-
313
- // Helper text / Supporting text
314
- &-helper {
315
- @include m.typography("body-small");
316
- position: absolute;
317
- bottom: -18px;
318
- left: 16px;
319
- margin-top: 4px;
320
- color: t.color("on-surface-variant");
321
-
322
- &--error {
323
- color: t.color("error");
324
- }
325
- }
326
-
327
- // Required indicator
328
- &-required {
329
- color: t.color("error");
330
- margin-left: 4px;
331
- }
332
-
333
- // Accessibility
334
- @include m.reduced-motion {
32
+ position: relative;
33
+ display: inline-flex;
34
+ flex-direction: column;
35
+ // min-width: 210px;
36
+ // align-self: flex-start; // Prevents growing to fill the container's height
37
+ flex: 0 0 auto; // Don't grow or shrink; keep natural size
38
+ // Label
335
39
  &-label {
336
- transition: none;
337
- }
40
+ @include m.typography("body-large");
41
+ user-select: none;
42
+ position: absolute;
43
+ left: 16px;
44
+ top: 50%;
45
+ transform: translateY(-50%);
46
+ transform-origin: left top;
47
+ pointer-events: none;
48
+ border-radius: 2px;
49
+ color: t.color("on-surface-variant");
50
+ transition:
51
+ transform v.motion("duration-short4") v.motion("easing-emphasized"),
52
+ color v.motion("duration-short2") v.motion("easing-standard"),
53
+ left v.motion("duration-short4") v.motion("easing-emphasized");
54
+ }
55
+
56
+ // Input element
57
+ &-input {
58
+ @include m.typography("body-large");
59
+ @include m.shape("extra-small");
60
+ padding: 13px 16px;
61
+ width: 100%;
62
+ height: 56px;
63
+ color: t.color("on-surface");
64
+ border: 0;
65
+ appearance: none;
66
+ outline: none;
67
+
68
+ // Animation to detect autofill
69
+ animation-name: onAutoFillCancel;
70
+ animation-duration: 10ms;
71
+
72
+ // Transition to help detect autofill changes
73
+ transition: background-color 0s ease-out 50000000s;
74
+
75
+ &::placeholder {
76
+ color: transparent;
77
+ }
338
78
 
339
- &-prefix,
340
- &-suffix,
341
- &-leading-icon,
342
- &-trailing-icon {
343
- transition: none;
344
- }
345
- }
79
+ // Autofill styles
80
+ &:-webkit-autofill {
81
+ animation-name: onAutoFillStart;
82
+ animation-duration: 10ms;
83
+ -webkit-text-fill-color: t.color("on-surface");
84
+ transition: background-color 5000s ease-in-out 0s; // Long transition to keep the background
85
+
86
+ & ~ .#{$component}-label {
87
+ transform: translateY(-95%) scale(0.75);
88
+ background-color: t.color("surface");
89
+ }
90
+ }
346
91
 
347
- // RTL support
348
- @include m.rtl {
349
- &-label {
350
- left: auto;
351
- right: 16px;
352
- transform-origin: right top;
353
- }
92
+ // Firefox autofill
93
+ &:autofill {
94
+ color: t.color("on-surface");
354
95
 
355
- &-required {
356
- margin-left: 0;
357
- margin-right: 4px;
358
- }
96
+ & ~ .#{$component}-label {
97
+ transform: translateY(-95%) scale(0.75);
98
+ background-color: t.color("surface");
99
+ }
100
+ }
359
101
 
360
- &-prefix {
361
- left: auto;
362
- right: 16px;
102
+ // Non-empty input should also float the label
103
+ &:not(:placeholder-shown) {
104
+ & ~ .#{$component}-label {
105
+ transform: translateY(-95%) scale(0.75);
106
+ }
107
+ }
363
108
  }
364
109
 
110
+ // Prefix text
111
+ &-prefix {
112
+ @include m.typography("body-large");
113
+ position: absolute;
114
+ left: 12px;
115
+ top: 50%;
116
+ transform: translateY(-50%);
117
+ color: t.color("on-surface");
118
+ pointer-events: none;
119
+ z-index: 2; // Increased to ensure it stays above input
120
+ white-space: nowrap; // Prevent text wrapping
121
+ max-width: 40%; // Prevent extreme overflow
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ transition: top v.motion("duration-short4")
125
+ v.motion("easing-emphasized"); // Add transition for top position
126
+ }
127
+
128
+ // Suffix text
365
129
  &-suffix {
366
- right: auto;
367
- left: 16px;
368
- }
369
-
130
+ @include m.typography("body-large");
131
+ position: absolute;
132
+ right: 16px;
133
+ top: 50%;
134
+ transform: translateY(-50%);
135
+ color: t.color("on-surface");
136
+ pointer-events: none;
137
+ z-index: 2; // Increased to ensure it stays above input
138
+ white-space: nowrap; // Prevent text wrapping
139
+ max-width: 40%; // Prevent extreme overflow
140
+ overflow: hidden;
141
+ text-overflow: ellipsis;
142
+ transition: top v.motion("duration-short4")
143
+ v.motion("easing-emphasized"); // Add transition for top position
144
+ }
145
+
146
+ // Leading icon
370
147
  &-leading-icon {
371
- left: auto;
372
- right: 12px;
148
+ opacity: 0.85;
149
+ position: absolute;
150
+ left: 12px;
151
+ top: 50%;
152
+ transform: translateY(-50%);
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ width: 24px;
157
+ height: 24px;
158
+ pointer-events: none;
159
+ color: t.color("on-surface-variant");
160
+ z-index: 1;
161
+ transition: top v.motion("duration-short4")
162
+ v.motion("easing-emphasized"); // Add transition for top position
163
+
164
+ svg {
165
+ width: 20px;
166
+ height: 20px;
167
+ }
373
168
  }
374
169
 
170
+ // Trailing icon
375
171
  &-trailing-icon {
376
- right: auto;
377
- left: 12px;
172
+ opacity: 0.85;
173
+ position: absolute;
174
+ right: 12px;
175
+ top: 50%;
176
+ transform: translateY(-50%);
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ width: 24px;
181
+ height: 24px;
182
+ color: t.color("on-surface-variant");
183
+ z-index: 1;
184
+ cursor: pointer;
185
+ transition: top v.motion("duration-short4")
186
+ v.motion("easing-emphasized"); // Add transition for top position
187
+
188
+ svg {
189
+ width: 20px;
190
+ height: 20px;
191
+ }
378
192
  }
379
193
 
194
+ // Adjustments when prefix/suffix are present - base case styling
195
+ // JavaScript will handle dynamic sizing, these are fallbacks
380
196
  &--with-prefix {
381
- .#{$component}-label {
382
- left: auto;
383
- // Default value - will be overridden by JS for precise positioning
384
- right: 48px;
385
- }
386
-
387
- .#{$component}-input {
388
- padding-left: 16px;
389
- // Default value - will be overridden by JS for precise padding
390
- padding-right: 48px;
391
- }
197
+ .#{$component}-label {
198
+ // Default value - will be overridden by JS for precise positioning
199
+ left: 48px;
200
+ }
201
+
202
+ .#{$component}-input {
203
+ // Default value - will be overridden by JS for precise padding
204
+ padding-left: 48px;
205
+ }
392
206
  }
393
207
 
394
208
  &--with-suffix {
395
- .#{$component}-input {
396
- padding-right: 16px;
397
- // Default value - will be overridden by JS for precise padding
398
- padding-left: 48px;
399
- }
209
+ .#{$component}-input {
210
+ // Default value - will be overridden by JS for precise padding
211
+ padding-right: 48px;
212
+ }
400
213
  }
401
214
 
215
+ // Adjustments when icons are present
402
216
  &--with-leading-icon {
403
- .#{$component}-label {
404
- left: auto;
405
- right: 44px;
406
- }
407
-
408
- .#{$component}-input {
409
- padding-left: 16px;
410
- padding-right: 44px;
411
- }
412
-
413
- &.#{$component}--with-prefix {
414
- .#{$component}-prefix {
415
- left: auto;
416
- right: 44px;
417
- }
418
-
419
217
  .#{$component}-label {
420
- left: auto;
421
- // Default value - will be overridden by JS for precise positioning
422
- right: 76px;
218
+ left: 44px;
423
219
  }
424
220
 
425
221
  .#{$component}-input {
426
- padding-left: 16px;
427
- // Default value - will be overridden by JS for precise padding
428
- padding-right: 76px;
222
+ padding-left: 44px;
223
+ }
224
+
225
+ // If there's also a prefix, adjust positions
226
+ &.#{$component}--with-prefix {
227
+ .#{$component}-prefix {
228
+ left: 44px;
229
+ }
230
+
231
+ .#{$component}-label {
232
+ // Default value - will be overridden by JS for precise positioning
233
+ left: 76px;
234
+ }
235
+
236
+ .#{$component}-input {
237
+ // Default value - will be overridden by JS for precise padding
238
+ padding-left: 76px;
239
+ }
429
240
  }
430
- }
431
241
  }
432
242
 
433
243
  &--with-trailing-icon {
434
- .#{$component}-input {
435
- padding-right: 16px;
436
- padding-left: 44px;
437
- }
438
-
439
- &.#{$component}--with-suffix {
440
- .#{$component}-suffix {
441
- right: auto;
442
- left: 44px;
244
+ .#{$component}-input {
245
+ padding-right: 44px;
443
246
  }
444
247
 
445
- .#{$component}-input {
446
- padding-right: 16px;
447
- // Default value - will be overridden by JS for precise padding
448
- padding-left: 76px;
248
+ // If there's also a suffix, adjust positions
249
+ &.#{$component}--with-suffix {
250
+ .#{$component}-suffix {
251
+ right: 44px;
252
+ }
253
+
254
+ .#{$component}-input {
255
+ // Default value - will be overridden by JS for precise padding
256
+ padding-right: 76px;
257
+ }
449
258
  }
450
- }
451
259
  }
452
- }
453
260
 
454
- // ===== FILLED VARIANT =====
455
- &--filled {
456
- .#{$component}-input {
457
- background-color: t.color("surface-container-highest");
458
- padding: 20px 16px 7px;
459
- border-bottom: 1px solid t.color("outline");
460
- border-radius: f.get-shape("extra-small") f.get-shape("extra-small") 0 0;
461
- @include m.motion-transition(background-color, border-color);
462
-
463
- // Autofill styles for filled variant
464
- &:-webkit-autofill {
465
- border-radius: f.get-shape("extra-small") f.get-shape("extra-small") 0 0;
261
+ // Error state
262
+ &--error {
263
+ border-color: t.color("error");
466
264
 
467
- & ~ .#{$component}-label {
468
- transform: translateY(-95%) scale(0.75);
469
- color: t.color("on-surface-variant");
265
+ .#{$component}-label {
266
+ color: t.color("error");
470
267
  }
471
- }
472
268
 
473
- &:autofill {
474
- & ~ .#{$component}-label {
475
- transform: translateY(-95%) scale(0.75);
476
- color: t.color("on-surface-variant");
269
+ .#{$component}-leading-icon,
270
+ .#{$component}-trailing-icon,
271
+ .#{$component}-prefix,
272
+ .#{$component}-suffix {
273
+ color: t.color("error");
477
274
  }
478
- }
479
- }
480
-
481
- &::before {
482
- content: "";
483
- position: absolute;
484
- opacity: 0;
485
- bottom: 0;
486
- width: 100%;
487
- height: 2px;
488
- background-color: t.color("primary");
489
- border-radius: 0;
490
- pointer-events: none;
491
- transition: 0.2s opacity ease;
492
275
  }
493
276
 
494
- // Populated field (not empty) or focused field label position
495
- &:not(.#{$component}--empty) .#{$component}-label,
496
- &.#{$component}--focused .#{$component}-label {
497
- transform: translateY(-95%) scale(0.75);
498
- // Don't specify left position here - let JS handle it
499
- }
277
+ // Disabled state
278
+ &--disabled {
279
+ .#{$component}-input {
280
+ opacity: 0.38;
281
+ border-color: t.color("on-surface");
282
+ background-color: t.alpha("on-surface", 0.04);
283
+ pointer-events: none;
284
+ }
500
285
 
501
- // CSS-only fallback for when input has value (works without JS)
502
- .#{$component}-input:not(:placeholder-shown) ~ .#{$component}-label {
503
- transform: translateY(-95%) scale(0.75);
504
- }
286
+ .#{$component}-label {
287
+ color: t.color("on-surface");
288
+ opacity: 0.38;
289
+ }
505
290
 
506
- // Position adjustments for prefix/suffix when in filled focused/populated state
507
- &.mtrl-textfield--with-prefix,
508
- &.mtrl-textfield--with-suffix {
509
- &:not(.#{$component}--empty),
510
- &.#{$component}--focused {
291
+ .#{$component}-leading-icon,
292
+ .#{$component}-trailing-icon,
511
293
  .#{$component}-prefix,
512
294
  .#{$component}-suffix {
513
- top: 34px; // Align with input text when focused or populated
295
+ color: t.color("on-surface");
296
+ opacity: 0.38;
514
297
  }
515
- }
516
298
  }
517
- // Focus state
518
- &.#{$component}--focused {
519
- .#{$component}-label {
520
- color: t.color("primary");
521
- }
522
299
 
523
- &::before {
524
- opacity: 1;
525
- }
300
+ // Disabled state - legacy support for direct input disabled
301
+ &-input:disabled {
302
+ opacity: 0.38;
303
+ border-color: t.color("on-surface");
304
+ background-color: t.alpha("on-surface", 0.04);
305
+ pointer-events: none;
306
+
307
+ & ~ .#{$component}-label,
308
+ & ~ .#{$component}-leading-icon,
309
+ & ~ .#{$component}-trailing-icon,
310
+ & ~ .#{$component}-prefix,
311
+ & ~ .#{$component}-suffix {
312
+ color: t.color("on-surface");
313
+ opacity: 0.38;
314
+ }
526
315
  }
527
316
 
528
- // Error state
529
- &.#{$component}--error {
530
- &::before {
531
- opacity: 1;
532
- background-color: t.color("error");
533
- }
317
+ // Helper text / Supporting text
318
+ &-helper {
319
+ @include m.typography("body-small");
320
+ position: absolute;
321
+ bottom: -18px;
322
+ left: 16px;
323
+ margin-top: 4px;
324
+ color: t.color("on-surface-variant");
325
+
326
+ &--error {
327
+ color: t.color("error");
328
+ }
329
+ }
534
330
 
535
- .#{$component}-label {
331
+ // Required indicator
332
+ &-required {
536
333
  color: t.color("error");
537
- }
334
+ margin-left: 4px;
538
335
  }
539
336
 
540
- // Disabled state
541
- &.#{$component}--disabled {
542
- border-bottom-color: t.alpha("on-surface", 0.38);
543
- pointer-events: none;
337
+ // Accessibility
338
+ @include m.reduced-motion {
339
+ &-label {
340
+ transition: none;
341
+ }
544
342
 
545
- .#{$component}-input {
546
- background-color: t.alpha("on-surface", 0.04);
547
- }
343
+ &-prefix,
344
+ &-suffix,
345
+ &-leading-icon,
346
+ &-trailing-icon {
347
+ transition: none;
348
+ }
548
349
  }
549
350
 
550
- // Prefix/suffix adjustments for filled variant
551
- &.#{$component}--with-prefix {
552
- .#{$component}-prefix {
553
- top: 28px; // Align with input text in filled variant - default state
554
- }
555
- }
351
+ // RTL support
352
+ @include m.rtl {
353
+ &-label {
354
+ left: auto;
355
+ right: 16px;
356
+ transform-origin: right top;
357
+ }
556
358
 
557
- &.#{$component}--with-suffix {
558
- .#{$component}-suffix {
559
- top: 28px; // Align with input text in filled variant - default state
560
- }
561
- }
359
+ &-required {
360
+ margin-left: 0;
361
+ margin-right: 4px;
362
+ }
562
363
 
563
- // Icon adjustments for filled variant
564
- &.#{$component}--with-leading-icon {
565
- .#{$component}-input {
566
- padding: 20px 16px 7px 44px;
567
- }
364
+ &-prefix {
365
+ left: auto;
366
+ right: 16px;
367
+ }
568
368
 
569
- .#{$component}-label {
570
- left: 44px;
571
- }
369
+ &-suffix {
370
+ right: auto;
371
+ left: 16px;
372
+ }
572
373
 
573
- .#{$component}-leading-icon {
574
- top: 28px;
575
- }
576
- }
374
+ &-leading-icon {
375
+ left: auto;
376
+ right: 12px;
377
+ }
577
378
 
578
- // Populated field (not empty) or focused field label position
579
- &:not(.#{$component}--empty) .#{$component}-label,
580
- &.#{$component}--focused .#{$component}-label {
581
- // Important change: For outlined variant, when focused/populated
582
- // we want to reset the left position back to default (or to JS calculated equivalent)
583
- // to handle the label moving up above the field
584
- // The JS will handle special positioning depending on if it's prefixed
585
- left: 16px;
586
- }
379
+ &-trailing-icon {
380
+ right: auto;
381
+ left: 12px;
382
+ }
587
383
 
588
- &.#{$component}--with-trailing-icon {
589
- .#{$component}-input {
590
- padding-right: 44px;
591
- }
384
+ &--with-prefix {
385
+ .#{$component}-label {
386
+ left: auto;
387
+ // Default value - will be overridden by JS for precise positioning
388
+ right: 48px;
389
+ }
390
+
391
+ .#{$component}-input {
392
+ padding-left: 16px;
393
+ // Default value - will be overridden by JS for precise padding
394
+ padding-right: 48px;
395
+ }
396
+ }
592
397
 
593
- .#{$component}-trailing-icon {
594
- top: 28px;
595
- }
596
- }
398
+ &--with-suffix {
399
+ .#{$component}-input {
400
+ padding-right: 16px;
401
+ // Default value - will be overridden by JS for precise padding
402
+ padding-left: 48px;
403
+ }
404
+ }
597
405
 
598
- // RTL support
599
- @include m.rtl {
600
- .#{$component}-label {
601
- left: auto;
602
- right: 16px;
603
- }
406
+ &--with-leading-icon {
407
+ .#{$component}-label {
408
+ left: auto;
409
+ right: 44px;
410
+ }
411
+
412
+ .#{$component}-input {
413
+ padding-left: 16px;
414
+ padding-right: 44px;
415
+ }
416
+
417
+ &.#{$component}--with-prefix {
418
+ .#{$component}-prefix {
419
+ left: auto;
420
+ right: 44px;
421
+ }
422
+
423
+ .#{$component}-label {
424
+ left: auto;
425
+ // Default value - will be overridden by JS for precise positioning
426
+ right: 76px;
427
+ }
428
+
429
+ .#{$component}-input {
430
+ padding-left: 16px;
431
+ // Default value - will be overridden by JS for precise padding
432
+ padding-right: 76px;
433
+ }
434
+ }
435
+ }
604
436
 
605
- &.#{$component}--with-leading-icon {
606
- .#{$component}-input {
607
- padding: 20px 44px 7px 16px;
437
+ &--with-trailing-icon {
438
+ .#{$component}-input {
439
+ padding-right: 16px;
440
+ padding-left: 44px;
441
+ }
442
+
443
+ &.#{$component}--with-suffix {
444
+ .#{$component}-suffix {
445
+ right: auto;
446
+ left: 44px;
447
+ }
448
+
449
+ .#{$component}-input {
450
+ padding-right: 16px;
451
+ // Default value - will be overridden by JS for precise padding
452
+ padding-left: 76px;
453
+ }
454
+ }
608
455
  }
456
+ }
609
457
 
458
+ // ===== FILLED VARIANT =====
459
+ &--filled {
610
460
  .#{$component}-label {
611
- left: auto;
612
- right: 44px;
461
+ opacity: 0.6;
613
462
  }
614
- }
615
-
616
- &.#{$component}--with-trailing-icon {
617
463
  .#{$component}-input {
618
- padding-right: 16px;
619
- padding-left: 44px;
464
+ background-color: t.color("surface-container-highest");
465
+ padding: 20px 16px 7px;
466
+ border-bottom: 1px solid t.color("outline");
467
+ border-radius: f.get-shape("extra-small") f.get-shape("extra-small")
468
+ 0 0;
469
+ @include m.motion-transition(background-color, border-color);
470
+
471
+ // Autofill styles for filled variant
472
+ &:-webkit-autofill {
473
+ border-radius: f.get-shape("extra-small")
474
+ f.get-shape("extra-small") 0 0;
475
+
476
+ & ~ .#{$component}-label {
477
+ transform: translateY(-95%) scale(0.75);
478
+ color: t.color("on-surface-variant");
479
+ }
480
+ }
481
+
482
+ &:autofill {
483
+ & ~ .#{$component}-label {
484
+ transform: translateY(-95%) scale(0.75);
485
+ color: t.color("on-surface-variant");
486
+ }
487
+ }
620
488
  }
621
- }
622
- }
623
- }
624
-
625
- // ===== OUTLINED VARIANT =====
626
- &--outlined {
627
- background-color: inherit;
628
- border-radius: f.get-shape("extra-small");
629
- @include m.motion-transition(border-color);
630
-
631
- .#{$component}-input {
632
- background-color: transparent;
633
- padding: 12px 15px 13px;
634
- border: 1px solid t.color("outline");
635
- @include m.motion-transition(padding);
636
-
637
- // Autofill styles for outlined variant
638
- &:-webkit-autofill {
639
- border-radius: f.get-shape("extra-small");
640
489
 
641
- & ~ .#{$component}-label {
642
- background-color: t.color("surface");
643
- transform: translateY(-145%) scale(0.75);
490
+ &::before {
491
+ content: "";
492
+ position: absolute;
493
+ opacity: 0;
494
+ bottom: 0;
495
+ width: 100%;
496
+ height: 2px;
497
+ background-color: t.color("primary");
498
+ border-radius: 0;
499
+ pointer-events: none;
500
+ transition: 0.2s opacity ease;
644
501
  }
645
- }
646
502
 
647
- &:autofill {
648
- & ~ .#{$component}-label {
649
- background-color: t.color("surface");
650
- transform: translateY(-145%) scale(0.75);
503
+ // Populated field (not empty) or focused field label position
504
+ &:not(.#{$component}--empty) .#{$component}-label,
505
+ &.#{$component}--focused .#{$component}-label {
506
+ transform: translateY(-95%) scale(0.75);
507
+ // Don't specify left position here - let JS handle it
651
508
  }
652
- }
653
- }
654
509
 
655
- .#{$component}-label {
656
- background-color: inherit;
657
- padding: 0 4px;
658
- left: 14px;
659
- top: 50%;
660
- }
510
+ // CSS-only fallback for when input has value (works without JS)
511
+ .#{$component}-input:not(:placeholder-shown) ~ .#{$component}-label {
512
+ transform: translateY(-95%) scale(0.75);
513
+ }
661
514
 
662
- &::before {
663
- content: "";
664
- position: absolute;
665
- opacity: 0;
666
- width: 100%;
667
- height: 100%;
668
- border: 1.5px solid t.color("primary");
669
- border-radius: f.get-shape("extra-small");
670
- pointer-events: none;
671
- transition: 0.1s opacity ease;
672
- }
515
+ // Position adjustments for prefix/suffix when in filled focused/populated state
516
+ &.mtrl-textfield--with-prefix,
517
+ &.mtrl-textfield--with-suffix {
518
+ &:not(.#{$component}--empty),
519
+ &.#{$component}--focused {
520
+ .#{$component}-prefix,
521
+ .#{$component}-suffix {
522
+ top: 34px; // Align with input text when focused or populated
523
+ }
524
+ }
525
+ }
526
+ // Focus state
527
+ &.#{$component}--focused {
528
+ .#{$component}-label {
529
+ color: t.color("primary");
530
+ }
673
531
 
674
- // Populated field (not empty) or focused field label position
675
- &:not(.#{$component}--empty) .#{$component}-label,
676
- &.#{$component}--focused .#{$component}-label {
677
- padding: 0 4px;
678
- transform: translateY(-147%) scale(0.75);
679
- // Important change: For outlined variant, when focused/populated
680
- // we want to reset the left position back to default (or to JS calculated equivalent)
681
- // to handle the label moving up above the field
682
- // The JS will handle special positioning depending on if it's prefixed
683
- left: 14px;
684
- }
532
+ &::before {
533
+ opacity: 1;
534
+ }
535
+ }
685
536
 
686
- // CSS-only fallback for when input has value (works without JS)
687
- .#{$component}-input:not(:placeholder-shown) ~ .#{$component}-label {
688
- padding: 0 4px;
689
- transform: translateY(-147%) scale(0.75);
690
- left: 14px;
691
- background-color: t.color("surface");
692
- }
537
+ // Error state
538
+ &.#{$component}--error {
539
+ &::before {
540
+ opacity: 1;
541
+ background-color: t.color("error");
542
+ }
693
543
 
694
- // Focus state
695
- &.#{$component}--focused {
696
- &::before {
697
- opacity: 1;
698
- border-width: 2px;
699
- }
700
- // &:hover {
701
- // &::before {
544
+ .#{$component}-label {
545
+ color: t.color("error");
546
+ }
547
+ }
702
548
 
703
- // }
704
- // }
549
+ // Disabled state
550
+ &.#{$component}--disabled {
551
+ border-bottom-color: t.alpha("on-surface", 0.38);
552
+ pointer-events: none;
705
553
 
706
- .#{$component}-label {
707
- color: t.color("primary");
708
- }
709
- }
554
+ .#{$component}-input {
555
+ background-color: t.alpha("on-surface", 0.04);
556
+ }
557
+ }
710
558
 
711
- // Error state
712
- &.#{$component}--error {
713
- &::before {
714
- opacity: 1;
715
- border: 2px solid t.color("error");
716
- }
559
+ // Prefix/suffix adjustments for filled variant
560
+ &.#{$component}--with-prefix {
561
+ .#{$component}-prefix {
562
+ top: 28px; // Align with input text in filled variant - default state
563
+ }
564
+ }
717
565
 
718
- .#{$component}-label {
719
- color: t.color("error");
720
- }
721
- }
566
+ &.#{$component}--with-suffix {
567
+ .#{$component}-suffix {
568
+ top: 28px; // Align with input text in filled variant - default state
569
+ }
570
+ }
722
571
 
723
- // Disabled state
724
- &.#{$component}--disabled {
725
- pointer-events: none;
726
- &::before {
727
- opacity: 1;
728
- border: 1px solid t.alpha("on-surface", 0.38);
729
- }
730
- }
572
+ // Icon adjustments for filled variant
573
+ &.#{$component}--with-leading-icon {
574
+ .#{$component}-input {
575
+ padding: 20px 16px 7px 44px;
576
+ }
731
577
 
732
- // Prefix/suffix vertical alignment for outlined variant
733
- &.#{$component}--with-prefix {
734
- .#{$component}-prefix {
735
- top: 50%; // Centered vertically in outlined variant
736
- }
737
- }
578
+ .#{$component}-label {
579
+ left: 44px;
580
+ }
738
581
 
739
- &.#{$component}--with-suffix {
740
- .#{$component}-suffix {
741
- top: 50%; // Centered vertically in outlined variant
742
- }
743
- }
582
+ .#{$component}-leading-icon {
583
+ top: 28px;
584
+ }
585
+ }
744
586
 
745
- // Icon adjustments for outlined variant
746
- &.#{$component}--with-leading-icon {
747
- .#{$component}-input {
748
- padding-left: 44px;
749
- }
750
-
751
- .#{$component}-label {
752
- left: 44px;
753
- }
754
-
755
- // Important change: For outlined variant, when focused/populated
756
- // we still reset to 12px position (default)
757
- &:not(.#{$component}--empty) .#{$component}-label,
758
- &.#{$component}--focused .#{$component}-label {
759
- left: 14px;
760
- }
761
- }
587
+ // Populated field (not empty) or focused field label position
588
+ &:not(.#{$component}--empty) .#{$component}-label,
589
+ &.#{$component}--focused .#{$component}-label {
590
+ // Important change: For outlined variant, when focused/populated
591
+ // we want to reset the left position back to default (or to JS calculated equivalent)
592
+ // to handle the label moving up above the field
593
+ // The JS will handle special positioning depending on if it's prefixed
594
+ left: 16px;
595
+ }
762
596
 
763
- &.#{$component}--with-trailing-icon {
764
- .#{$component}-input {
765
- padding-right: 44px;
766
- }
767
- }
597
+ &.#{$component}--with-trailing-icon {
598
+ .#{$component}-input {
599
+ padding-right: 44px;
600
+ }
768
601
 
769
- // RTL support
770
- @include m.rtl {
771
- &:not(.#{$component}--empty) .#{$component}-label,
772
- &.#{$component}--focused .#{$component}-label {
773
- left: auto;
774
- right: 12px;
775
- }
602
+ .#{$component}-trailing-icon {
603
+ top: 28px;
604
+ }
605
+ }
776
606
 
777
- &.#{$component}--focused .#{$component}-label {
778
- right: 12px;
779
- }
607
+ // RTL support
608
+ @include m.rtl {
609
+ .#{$component}-label {
610
+ left: auto;
611
+ right: 16px;
612
+ }
613
+
614
+ &.#{$component}--with-leading-icon {
615
+ .#{$component}-input {
616
+ padding: 20px 44px 7px 16px;
617
+ }
618
+
619
+ .#{$component}-label {
620
+ left: auto;
621
+ right: 44px;
622
+ }
623
+ }
624
+
625
+ &.#{$component}--with-trailing-icon {
626
+ .#{$component}-input {
627
+ padding-right: 16px;
628
+ padding-left: 44px;
629
+ }
630
+ }
631
+ }
632
+ }
780
633
 
781
- &.#{$component}--error .#{$component}-label {
782
- right: 12px;
783
- }
634
+ // ===== OUTLINED VARIANT =====
635
+ &--outlined {
636
+ background-color: inherit;
637
+ border-radius: f.get-shape("extra-small");
638
+ @include m.motion-transition(border-color);
784
639
 
785
- &.#{$component}--with-leading-icon {
786
640
  .#{$component}-input {
787
- padding-left: 16px;
788
- padding-right: 44px;
641
+ background-color: transparent;
642
+ padding: 12px 15px 13px;
643
+ border: 1px solid t.color("outline");
644
+ @include m.motion-transition(padding);
645
+
646
+ // Autofill styles for outlined variant
647
+ &:-webkit-autofill {
648
+ border-radius: f.get-shape("extra-small");
649
+
650
+ & ~ .#{$component}-label {
651
+ background-color: t.color("surface");
652
+ transform: translateY(-145%) scale(0.75);
653
+ }
654
+ }
655
+
656
+ &:autofill {
657
+ & ~ .#{$component}-label {
658
+ background-color: t.color("surface");
659
+ transform: translateY(-145%) scale(0.75);
660
+ }
661
+ }
789
662
  }
790
663
 
791
664
  .#{$component}-label {
792
- left: auto;
793
- right: 44px;
665
+ opacity: 0.5;
666
+ background-color: inherit;
667
+ padding: 0 4px;
668
+ left: 14px;
669
+ top: 50%;
670
+ }
671
+
672
+ &::before {
673
+ content: "";
674
+ position: absolute;
675
+ opacity: 0;
676
+ width: 100%;
677
+ height: 100%;
678
+ border: 1.5px solid t.color("primary");
679
+ border-radius: f.get-shape("extra-small");
680
+ pointer-events: none;
681
+ transition: 0.1s opacity ease;
794
682
  }
795
683
 
684
+ // Populated field (not empty) or focused field label position
796
685
  &:not(.#{$component}--empty) .#{$component}-label,
797
686
  &.#{$component}--focused .#{$component}-label {
798
- // Reset to default value for focused state
799
- right: 12px;
800
- left: auto;
687
+ padding: 0 4px;
688
+ opacity: 1;
689
+ transform: translateY(-147%) scale(0.75);
690
+ // Important change: For outlined variant, when focused/populated
691
+ // we want to reset the left position back to default (or to JS calculated equivalent)
692
+ // to handle the label moving up above the field
693
+ // The JS will handle special positioning depending on if it's prefixed
694
+ left: 14px;
801
695
  }
802
- }
803
696
 
804
- &.#{$component}--with-trailing-icon {
805
- .#{$component}-input {
806
- padding-right: 16px;
807
- padding-left: 44px;
697
+ // CSS-only fallback for when input has value (works without JS)
698
+ .#{$component}-input:not(:placeholder-shown) ~ .#{$component}-label {
699
+ padding: 0 4px;
700
+ transform: translateY(-147%) scale(0.75);
701
+ left: 14px;
702
+ background-color: t.color("surface");
808
703
  }
809
- }
810
- }
811
- }
812
-
813
- // Multiline styles
814
- &--multiline {
815
- .#{$component}-input {
816
- min-height: 100px;
817
- height: auto;
818
- resize: vertical;
819
- padding-top: 12px;
820
- }
821
704
 
822
- .#{$component}-prefix,
823
- .#{$component}-suffix {
824
- top: 28px;
825
- }
705
+ // Focus state
706
+ &.#{$component}--focused {
707
+ &::before {
708
+ opacity: 1;
709
+ border-width: 2px;
710
+ }
711
+ // &:hover {
712
+ // &::before {
713
+
714
+ // }
715
+ // }
716
+
717
+ .#{$component}-label {
718
+ color: t.color("primary");
719
+ }
720
+ }
826
721
 
827
- .#{$component}-label {
828
- top: 24px;
829
- }
830
- }
831
-
832
- // Support for multiline inputs
833
- &-input[type="multiline"] {
834
- min-height: 100px;
835
- height: auto; // Allow height to adjust based on content
836
- max-height: none; // Remove max-height constraint from regular inputs
837
- flex-shrink: 1; // Allow some shrinking for multiline
838
-
839
- & ~ .#{$component}-leading-icon,
840
- & ~ .#{$component}-trailing-icon,
841
- & ~ .#{$component}-prefix,
842
- & ~ .#{$component}-suffix {
843
- top: 20px;
844
- transform: none;
845
- }
846
- }
847
-
848
- // ===== DENSITY VARIANTS =====
849
- // Compact density (40px height)
850
- &--density-compact {
851
- .#{$component}-input {
852
- height: 40px;
853
- padding: 8px 16px;
854
- @include m.typography("body-medium"); // Slightly smaller text
855
- }
722
+ // Error state
723
+ &.#{$component}--error {
724
+ &::before {
725
+ opacity: 1;
726
+ border: 2px solid t.color("error");
727
+ }
856
728
 
857
- // Adjust label position for compact
858
- .#{$component}-label {
859
- @include m.typography("body-medium");
860
- }
729
+ .#{$component}-label {
730
+ color: t.color("error");
731
+ }
732
+ }
861
733
 
862
- // Adjust icon positions for compact height
863
- .#{$component}-leading-icon,
864
- .#{$component}-trailing-icon {
865
- width: 20px;
866
- height: 20px;
734
+ // Disabled state
735
+ &.#{$component}--disabled {
736
+ pointer-events: none;
737
+ &::before {
738
+ opacity: 1;
739
+ border: 1px solid t.alpha("on-surface", 0.38);
740
+ }
741
+ }
867
742
 
868
- svg {
869
- width: 16px;
870
- height: 16px;
871
- }
872
- }
743
+ // Prefix/suffix vertical alignment for outlined variant
744
+ &.#{$component}--with-prefix {
745
+ .#{$component}-prefix {
746
+ top: 50%; // Centered vertically in outlined variant
747
+ }
748
+ }
873
749
 
874
- // Adjust prefix/suffix position for compact
875
- .#{$component}-prefix,
876
- .#{$component}-suffix {
877
- @include m.typography("body-medium");
878
- }
750
+ &.#{$component}--with-suffix {
751
+ .#{$component}-suffix {
752
+ top: 50%; // Centered vertically in outlined variant
753
+ }
754
+ }
879
755
 
880
- // Filled variant with compact density
881
- &.#{$component}--filled {
882
- .#{$component}-input {
883
- padding: 12px 16px 4px; // Adjusted for filled variant
884
- }
885
-
886
- // Populated/focused label position
887
- &:not(.#{$component}--empty) .#{$component}-label,
888
- &.#{$component}--focused .#{$component}-label {
889
- transform: translateY(-90%) scale(0.75); // Adjusted for compact height
890
- }
891
-
892
- // Adjust prefix/suffix position when focused/populated
893
- &.mtrl-textfield--with-prefix,
894
- &.mtrl-textfield--with-suffix {
895
- &:not(.#{$component}--empty),
896
- &.#{$component}--focused {
897
- .#{$component}-prefix,
898
- .#{$component}-suffix {
899
- top: 22px; // Adjusted for compact filled variant
900
- }
901
- }
902
- }
903
-
904
- // Adjust icons for filled compact
905
- .#{$component}-leading-icon,
906
- .#{$component}-trailing-icon {
907
- top: 20px; // Adjusted for compact filled
908
- }
909
- }
756
+ // Icon adjustments for outlined variant
757
+ &.#{$component}--with-leading-icon {
758
+ .#{$component}-input {
759
+ padding-left: 44px;
760
+ }
761
+
762
+ .#{$component}-label {
763
+ left: 44px;
764
+ }
765
+
766
+ // Important change: For outlined variant, when focused/populated
767
+ // we still reset to 12px position (default)
768
+ &:not(.#{$component}--empty) .#{$component}-label,
769
+ &.#{$component}--focused .#{$component}-label {
770
+ left: 14px;
771
+ }
772
+ }
910
773
 
911
- // Outlined variant with compact density
912
- &.#{$component}--outlined {
913
- .#{$component}-input {
914
- padding: 8px 15px 9px;
915
- }
916
-
917
- // Focused/populated position
918
- &:not(.#{$component}--empty) .#{$component}-label,
919
- &.#{$component}--focused .#{$component}-label {
920
- transform: translateY(-130%) scale(0.75); // Same as default, scale is important
921
- }
922
- }
774
+ &.#{$component}--with-trailing-icon {
775
+ .#{$component}-input {
776
+ padding-right: 44px;
777
+ }
778
+ }
923
779
 
924
- // Multiline with compact density
925
- &.#{$component}--multiline {
926
- .#{$component}-input {
927
- min-height: 40px;
928
- padding: 8px 16px;
929
- }
780
+ // RTL support
781
+ @include m.rtl {
782
+ &:not(.#{$component}--empty) .#{$component}-label,
783
+ &.#{$component}--focused .#{$component}-label {
784
+ left: auto;
785
+ right: 12px;
786
+ }
787
+
788
+ &.#{$component}--focused .#{$component}-label {
789
+ right: 12px;
790
+ }
791
+
792
+ &.#{$component}--error .#{$component}-label {
793
+ right: 12px;
794
+ }
795
+
796
+ &.#{$component}--with-leading-icon {
797
+ .#{$component}-input {
798
+ padding-left: 16px;
799
+ padding-right: 44px;
800
+ }
801
+
802
+ .#{$component}-label {
803
+ left: auto;
804
+ right: 44px;
805
+ }
806
+
807
+ &:not(.#{$component}--empty) .#{$component}-label,
808
+ &.#{$component}--focused .#{$component}-label {
809
+ // Reset to default value for focused state
810
+ right: 12px;
811
+ left: auto;
812
+ }
813
+ }
814
+
815
+ &.#{$component}--with-trailing-icon {
816
+ .#{$component}-input {
817
+ padding-right: 16px;
818
+ padding-left: 44px;
819
+ }
820
+ }
821
+ }
930
822
  }
931
823
 
932
- // Adjust element positions for compact with icons
933
- &.#{$component}--with-leading-icon {
934
- .#{$component}-label {
935
- left: 40px; // Reduced from 44px
936
- }
937
-
938
- .#{$component}-input {
939
- padding-left: 40px;
940
- }
941
-
942
- &.#{$component}--with-prefix {
943
- .#{$component}-prefix {
944
- left: 40px;
824
+ // Multiline styles
825
+ &--multiline {
826
+ .#{$component}-input {
827
+ min-height: 100px;
828
+ height: auto;
829
+ resize: vertical;
830
+ padding-top: 12px;
945
831
  }
946
832
 
947
- .#{$component}-label {
948
- left: 68px; // Adjusted for compact
833
+ .#{$component}-prefix,
834
+ .#{$component}-suffix {
835
+ top: 28px;
949
836
  }
950
837
 
951
- .#{$component}-input {
952
- padding-left: 68px;
838
+ .#{$component}-label {
839
+ top: 24px;
953
840
  }
954
- }
955
841
  }
956
842
 
957
- &.#{$component}--with-trailing-icon {
958
- .#{$component}-input {
959
- padding-right: 40px;
960
- }
843
+ // Support for multiline inputs
844
+ &-input[type="multiline"] {
845
+ min-height: 100px;
846
+ height: auto; // Allow height to adjust based on content
847
+ max-height: none; // Remove max-height constraint from regular inputs
848
+ flex-shrink: 1; // Allow some shrinking for multiline
961
849
 
962
- &.#{$component}--with-suffix {
963
- .#{$component}-suffix {
964
- right: 40px;
850
+ & ~ .#{$component}-leading-icon,
851
+ & ~ .#{$component}-trailing-icon,
852
+ & ~ .#{$component}-prefix,
853
+ & ~ .#{$component}-suffix {
854
+ top: 20px;
855
+ transform: none;
965
856
  }
857
+ }
966
858
 
859
+ // ===== DENSITY VARIANTS =====
860
+ // Compact density (40px height)
861
+ &--density-compact {
967
862
  .#{$component}-input {
968
- padding-right: 68px;
863
+ height: 40px;
864
+ padding: 8px 16px;
865
+ @include m.typography("body-medium"); // Slightly smaller text
969
866
  }
970
- }
971
- }
972
867
 
973
- // RTL adjustments for compact density
974
- @include m.rtl {
975
- &.#{$component}--with-leading-icon {
868
+ // Adjust label position for compact
976
869
  .#{$component}-label {
977
- left: auto;
978
- right: 40px;
870
+ @include m.typography("body-medium");
979
871
  }
980
872
 
981
- .#{$component}-input {
982
- padding-left: 16px;
983
- padding-right: 40px;
873
+ // Adjust icon positions for compact height
874
+ .#{$component}-leading-icon,
875
+ .#{$component}-trailing-icon {
876
+ width: 20px;
877
+ height: 20px;
878
+
879
+ svg {
880
+ width: 16px;
881
+ height: 16px;
882
+ }
984
883
  }
985
884
 
986
- &.#{$component}--with-prefix {
987
- .#{$component}-prefix {
988
- left: auto;
989
- right: 40px;
990
- }
885
+ // Adjust prefix/suffix position for compact
886
+ .#{$component}-prefix,
887
+ .#{$component}-suffix {
888
+ @include m.typography("body-medium");
889
+ }
991
890
 
992
- .#{$component}-label {
993
- left: auto;
994
- right: 68px;
995
- }
891
+ // Filled variant with compact density
892
+ &.#{$component}--filled {
893
+ .#{$component}-input {
894
+ padding: 12px 16px 4px; // Adjusted for filled variant
895
+ }
896
+
897
+ // Populated/focused label position
898
+ &:not(.#{$component}--empty) .#{$component}-label,
899
+ &.#{$component}--focused .#{$component}-label {
900
+ transform: translateY(-90%) scale(0.75); // Adjusted for compact height
901
+ }
902
+
903
+ // Adjust prefix/suffix position when focused/populated
904
+ &.mtrl-textfield--with-prefix,
905
+ &.mtrl-textfield--with-suffix {
906
+ &:not(.#{$component}--empty),
907
+ &.#{$component}--focused {
908
+ .#{$component}-prefix,
909
+ .#{$component}-suffix {
910
+ top: 22px; // Adjusted for compact filled variant
911
+ }
912
+ }
913
+ }
914
+
915
+ // Adjust icons for filled compact
916
+ .#{$component}-leading-icon,
917
+ .#{$component}-trailing-icon {
918
+ top: 20px; // Adjusted for compact filled
919
+ }
920
+ }
996
921
 
997
- .#{$component}-input {
998
- padding-left: 16px;
999
- padding-right: 68px;
1000
- }
922
+ // Outlined variant with compact density
923
+ &.#{$component}--outlined {
924
+ .#{$component}-input {
925
+ padding: 9px 15px 8px;
926
+ }
927
+
928
+ // Focused/populated position
929
+ &:not(.#{$component}--empty) .#{$component}-label,
930
+ &.#{$component}--focused .#{$component}-label {
931
+ transform: translateY(-130%) scale(0.75); // Same as default, scale is important
932
+ }
1001
933
  }
1002
- }
1003
934
 
1004
- &.#{$component}--with-trailing-icon {
1005
- .#{$component}-input {
1006
- padding-right: 16px;
1007
- padding-left: 40px;
935
+ // Multiline with compact density
936
+ &.#{$component}--multiline {
937
+ .#{$component}-input {
938
+ min-height: 40px;
939
+ padding: 8px 16px;
940
+ }
1008
941
  }
1009
942
 
1010
- &.#{$component}--with-suffix {
1011
- .#{$component}-suffix {
1012
- right: auto;
1013
- left: 40px;
1014
- }
943
+ // Adjust element positions for compact with icons
944
+ &.#{$component}--with-leading-icon {
945
+ .#{$component}-label {
946
+ left: 40px; // Reduced from 44px
947
+ }
948
+
949
+ .#{$component}-input {
950
+ padding-left: 40px;
951
+ }
952
+
953
+ &.#{$component}--with-prefix {
954
+ .#{$component}-prefix {
955
+ left: 40px;
956
+ }
957
+
958
+ .#{$component}-label {
959
+ left: 68px; // Adjusted for compact
960
+ }
961
+
962
+ .#{$component}-input {
963
+ padding-left: 68px;
964
+ }
965
+ }
966
+ }
967
+
968
+ &.#{$component}--with-trailing-icon {
969
+ .#{$component}-input {
970
+ padding-right: 40px;
971
+ }
972
+
973
+ &.#{$component}--with-suffix {
974
+ .#{$component}-suffix {
975
+ right: 40px;
976
+ }
977
+
978
+ .#{$component}-input {
979
+ padding-right: 68px;
980
+ }
981
+ }
982
+ }
1015
983
 
1016
- .#{$component}-input {
1017
- padding-right: 16px;
1018
- padding-left: 68px;
1019
- }
984
+ // RTL adjustments for compact density
985
+ @include m.rtl {
986
+ &.#{$component}--with-leading-icon {
987
+ .#{$component}-label {
988
+ left: auto;
989
+ right: 40px;
990
+ }
991
+
992
+ .#{$component}-input {
993
+ padding-left: 16px;
994
+ padding-right: 40px;
995
+ }
996
+
997
+ &.#{$component}--with-prefix {
998
+ .#{$component}-prefix {
999
+ left: auto;
1000
+ right: 40px;
1001
+ }
1002
+
1003
+ .#{$component}-label {
1004
+ left: auto;
1005
+ right: 68px;
1006
+ }
1007
+
1008
+ .#{$component}-input {
1009
+ padding-left: 16px;
1010
+ padding-right: 68px;
1011
+ }
1012
+ }
1013
+ }
1014
+
1015
+ &.#{$component}--with-trailing-icon {
1016
+ .#{$component}-input {
1017
+ padding-right: 16px;
1018
+ padding-left: 40px;
1019
+ }
1020
+
1021
+ &.#{$component}--with-suffix {
1022
+ .#{$component}-suffix {
1023
+ right: auto;
1024
+ left: 40px;
1025
+ }
1026
+
1027
+ .#{$component}-input {
1028
+ padding-right: 16px;
1029
+ padding-left: 68px;
1030
+ }
1031
+ }
1032
+ }
1020
1033
  }
1021
- }
1022
1034
  }
1023
- }
1024
1035
  }