UNPKG

54.9 kBSCSSView Raw
1//
2// Copyright 2020 Google Inc.
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21//
22
23// Selector '.mdc-*' should only be used in this project.
24// stylelint-disable selector-class-pattern --
25// NOTE: this is the implementation of the aforementioned classes.
26
27@use 'sass:math';
28@use 'sass:color';
29@use 'sass:list';
30@use 'sass:map';
31@use 'sass:meta';
32@use '@material/tokens/resolvers';
33@use '@material/density/functions' as density-functions;
34@use '@material/density/variables' as density-variables;
35@use '@material/elevation/elevation-theme';
36@use '@material/feature-targeting/feature-targeting';
37@use '@material/floating-label/mixins' as floating-label-mixins;
38@use '@material/floating-label/variables' as floating-label-variables;
39@use '@material/line-ripple/mixins' as line-ripple-mixins;
40@use '@material/list/mixins' as list-mixins;
41@use '@material/list/evolution-mixins' as list-evolution-mixins;
42@use '@material/menu-surface/mixins' as menu-surface-mixins;
43@use '@material/notched-outline/mixins' as notched-outline-mixins;
44@use '@material/notched-outline/variables' as notched-outline-variables;
45@use '@material/rtl/rtl';
46@use '@material/shape/functions' as shape-functions;
47@use '@material/shape/mixins' as shape-mixins;
48@use '@material/theme/custom-properties';
49@use '@material/theme/gss';
50@use '@material/theme/mixins' as theme-mixins;
51@use '@material/theme/state';
52@use '@material/theme/theme';
53@use '@material/theme/variables' as theme-variables;
54@use '@material/typography/mixins' as typography-mixins;
55@use '@material/typography/typography';
56@use './select-icon-theme';
57@use './select-helper-text-theme';
58
59$ripple-target: '.mdc-select__ripple';
60
61@function get-outlined-label-position-y($select-anchor-height) {
62 @return math.div($select-anchor-height, 2) +
63 math.div(notched-outline-variables.$label-box-height, 2);
64}
65
66$arrow-padding: 52px !default;
67$label-padding: 16px !default;
68$height: 56px !default;
69$minimum-height-for-filled-label: 52px !default;
70$filled-baseline-top: 40px !default;
71$selected-text-height: 28px !default;
72$anchor-padding-left: 16px !default;
73$anchor-padding-left-with-leading-icon: 0 !default;
74$anchor-padding-right: 0 !default;
75$outlined-stroke-width: 2px !default;
76$default-width: 200px !default;
77$shape-radius: small !default;
78
79$minimum-height: 40px !default;
80$minimum-height-for-filled-label: 52px !default;
81$maximum-height: $height !default;
82$density-scale: density-variables.$default-scale !default;
83$density-config: (
84 height: (
85 default: $height,
86 maximum: $maximum-height,
87 minimum: $minimum-height,
88 ),
89) !default;
90
91$ink-color: rgba(theme-variables.prop-value(on-surface), 0.87) !default;
92$dropdown-icon-color: rgba(
93 theme-variables.prop-value(on-surface),
94 0.54
95) !default;
96$label-color: rgba(theme-variables.prop-value(on-surface), 0.6) !default;
97$focused-label-color: rgba(theme-variables.prop-value(primary), 0.87) !default;
98$bottom-line-idle-color: rgba(
99 theme-variables.prop-value(on-surface),
100 0.42
101) !default;
102$bottom-line-hover-color: rgba(
103 theme-variables.prop-value(on-surface),
104 0.87
105) !default;
106
107$fill-color: color.mix(
108 theme-variables.prop-value(on-surface),
109 theme-variables.prop-value(surface),
110 4%
111) !default;
112
113// Disabled Styles
114$disabled-label-color: rgba(
115 theme-variables.prop-value(on-surface),
116 0.38
117) !default;
118$disabled-ink-color: rgba(
119 theme-variables.prop-value(on-surface),
120 0.38
121) !default;
122$disabled-fill-color: color.mix(
123 theme-variables.prop-value(on-surface),
124 theme-variables.prop-value(surface),
125 2%
126) !default;
127$disabled-fill-border: rgba(
128 theme-variables.prop-value(on-surface),
129 0.06
130) !default;
131$disabled-bottom-line-color: rgba(
132 theme-variables.prop-value(on-surface),
133 0.06
134) !default;
135$disabled-dropdown-icon-color: rgba(
136 theme-variables.prop-value(on-surface),
137 0.38
138) !default;
139$disabled-outline-color: rgba(
140 theme-variables.prop-value(on-surface),
141 0.06
142) !default;
143
144$outlined-idle-border: rgba(
145 theme-variables.prop-value(on-surface),
146 0.38
147) !default;
148$outlined-hover-border: rgba(
149 theme-variables.prop-value(on-surface),
150 0.87
151) !default;
152
153$label-position-y: 106% !default;
154$outline-label-offset: 16px !default;
155$outlined-label-position-y: get-outlined-label-position-y($height) !default;
156$outlined-with-leading-icon-label-position-x: 32px !default;
157
158$dropdown-transition-duration: 150ms !default;
159// Transition durartions to active state
160$icon-active-fade-out-duration: 0.33 * $dropdown-transition-duration !default;
161$icon-active-fade-in-duration: 0.67 * $dropdown-transition-duration !default;
162// Transition durartions to inactive state
163$icon-inactive-fade-out-duration: 0.5 * $dropdown-transition-duration !default;
164$icon-inactive-fade-in-duration: 0.5 * $dropdown-transition-duration !default;
165
166// Error colors
167$error-color: error !default;
168
169$_light-theme: (
170 // Implement `menu-cascading-menu-indicator-icon-color` when select supports.
171 // Implement `menu-cascading-menu-indicator-icon-size` when select supports.
172 // Implement `menu-container-surface-tint-layer-color` when select supports.
173 // Implement `text-field-disabled-trailing-icon-color` when select supports.
174 // Implement `text-field-hover-trailing-icon-color` when select supports.
175 // Implement `text-field-focus-trailing-icon-color` when select supports.
176 // Implement `text-field-error-trailing-icon-color` when select supports.
177 // Implement `text-field-error-hover-trailing-icon-color` when select supports.
178 // Implement `text-field-error-focus-trailing-icon-color` when select supports.
179 // Implement `text-field-trailing-icon-color` when select supports.
180 // Implement `text-field-trailing-icon-size` when select supports.
181 // Implement `text-field-error-hover-state-layer-color` when select supports.
182 // Implement `text-field-error-hover-state-layer-opacity` when select supports.
183 // Implement `text-field-hover-state-layer-color` when select supports.
184 // Implement `text-field-hover-state-layer-opacity` when select supports.
185 menu-container-color: null,
186 menu-container-elevation: null,
187 menu-container-shadow-color: null,
188 menu-container-shape: null,
189 menu-divider-color: null,
190 menu-divider-height: null,
191 menu-list-item-container-height: null,
192 menu-list-item-label-text-color: null,
193 menu-list-item-label-text-font: null,
194 menu-list-item-label-text-line-height: null,
195 menu-list-item-label-text-size: null,
196 menu-list-item-label-text-tracking: null,
197 menu-list-item-label-text-weight: null,
198 menu-list-item-selected-container-color: null,
199 menu-list-item-with-leading-icon-leading-icon-color: null,
200 menu-list-item-with-leading-icon-leading-icon-size: null,
201 menu-list-item-with-trailing-icon-trailing-icon-color: null,
202 menu-list-item-with-trailing-icon-trailing-icon-size: null,
203 text-field-active-indicator-color: null,
204 text-field-active-indicator-height: null,
205 text-field-caret-color: null,
206 // Token key `text-field-hover-caret-color` not available on DSDB.
207 text-field-hover-caret-color: null,
208 // Token key `text-field-focus-caret-color` not available on DSDB.
209 text-field-focus-caret-color: null,
210 text-field-container-color: null,
211 text-field-container-height: null,
212 text-field-container-shape: null,
213 text-field-disabled-active-indicator-color: null,
214 text-field-disabled-active-indicator-height: null,
215 text-field-disabled-active-indicator-opacity: null,
216 text-field-disabled-container-color: null,
217 text-field-disabled-container-opacity: null,
218 text-field-disabled-input-text-color: null,
219 text-field-disabled-input-text-opacity: null,
220 text-field-disabled-label-text-color: null,
221 text-field-disabled-label-text-opacity: null,
222 text-field-disabled-leading-icon-color: null,
223 text-field-disabled-leading-icon-opacity: null,
224 text-field-disabled-outline-color: null,
225 text-field-disabled-outline-opacity: null,
226 text-field-disabled-outline-width: null,
227 text-field-disabled-supporting-text-color: null,
228 text-field-disabled-supporting-text-opacity: null,
229 text-field-disabled-trailing-icon-opacity: null,
230 text-field-error-active-indicator-color: null,
231 text-field-error-focus-active-indicator-color: null,
232 // Token key `text-field-error-caret-color` not available on DSDB.
233 text-field-error-caret-color: null,
234 // Token key `text-field-error-hover-caret-color` not available on DSDB.
235 text-field-error-hover-caret-color: null,
236 text-field-error-focus-caret-color: null,
237 text-field-error-focus-input-text-color: null,
238 text-field-error-focus-label-text-color: null,
239 text-field-error-focus-leading-icon-color: null,
240 text-field-error-focus-outline-color: null,
241 text-field-error-focus-supporting-text-color: null,
242 text-field-error-hover-active-indicator-color: null,
243 text-field-error-hover-input-text-color: null,
244 text-field-error-hover-label-text-color: null,
245 text-field-error-hover-leading-icon-color: null,
246 text-field-error-hover-outline-color: null,
247 text-field-error-hover-supporting-text-color: null,
248 text-field-error-input-text-color: null,
249 text-field-error-label-text-color: null,
250 text-field-error-leading-icon-color: null,
251 text-field-error-outline-color: null,
252 text-field-error-supporting-text-color: null,
253 text-field-focus-active-indicator-color: null,
254 text-field-focus-active-indicator-height: null,
255 text-field-focus-input-text-color: null,
256 text-field-focus-label-text-color: null,
257 text-field-focus-leading-icon-color: null,
258 text-field-focus-outline-color: null,
259 text-field-focus-outline-width: null,
260 text-field-focus-supporting-text-color: null,
261 text-field-hover-active-indicator-color: null,
262 text-field-hover-active-indicator-height: null,
263 text-field-hover-input-text-color: null,
264 text-field-hover-label-text-color: null,
265 text-field-hover-leading-icon-color: null,
266 text-field-hover-outline-color: null,
267 text-field-hover-outline-width: null,
268 text-field-hover-supporting-text-color: null,
269 text-field-input-text-color: null,
270 text-field-input-text-font: null,
271 text-field-input-text-line-height: null,
272 text-field-input-text-size: null,
273 text-field-input-text-tracking: null,
274 text-field-input-text-weight: null,
275 text-field-label-text-color: null,
276 text-field-label-text-font: null,
277 text-field-label-text-line-height: null,
278 text-field-label-text-populated-line-height: null,
279 text-field-label-text-populated-size: null,
280 text-field-label-text-size: null,
281 text-field-label-text-tracking: null,
282 text-field-label-text-weight: null,
283 text-field-leading-icon-color: null,
284 text-field-leading-icon-size: null,
285 text-field-outline-color: null,
286 text-field-outline-width: null,
287 text-field-supporting-text-color: null,
288 text-field-supporting-text-font: null,
289 text-field-supporting-text-line-height: null,
290 text-field-supporting-text-size: null,
291 text-field-supporting-text-tracking: null,
292 text-field-supporting-text-weight: null
293);
294
295@mixin theme-styles($theme, $resolvers: resolvers.$material) {
296 @include theme.validate-theme-keys($_light-theme, $theme);
297
298 @include container-fill-color(
299 (
300 default: map.get($theme, text-field-container-color),
301 disabled: map.get($theme, text-field-disabled-container-color),
302 )
303 );
304 @include outline-color(
305 (
306 default: map.get($theme, text-field-outline-color),
307 hover: map.get($theme, text-field-hover-outline-color),
308 focus: map.get($theme, text-field-focus-outline-color),
309 disabled: map.get($theme, text-field-disabled-outline-color),
310 )
311 );
312 @include _error-outline-color(
313 (
314 default: map.get($theme, text-field-error-outline-color),
315 hover: map.get($theme, text-field-error-hover-outline-color),
316 focus: map.get($theme, text-field-error-focus-outline-color),
317 )
318 );
319 @include outline-width(
320 (
321 default: map.get($theme, text-field-outline-width),
322 hover: map.get($theme, text-field-hover-outline-width),
323 focus: map.get($theme, text-field-focus-outline-width),
324 )
325 );
326 @include _menu-container-color(map.get($theme, menu-container-color));
327 @include _menu-container-elevation(
328 map.get($resolvers, elevation),
329 $shadow-color: map.get($theme, menu-container-shadow-color),
330 $elevation: map.get($theme, menu-container-elevation)
331 );
332 @include _menu-container-shape(map.get($theme, menu-container-shape));
333 @include _menu-divider-color(map.get($theme, menu-divider-color));
334 @include _menu-divider-height(map.get($theme, menu-divider-height));
335 @include _menu-list-item-container-height(
336 map.get($theme, menu-list-item-container-height)
337 );
338 @include _menu-list-item-label-text-color(
339 map.get($theme, menu-list-item-label-text-color)
340 );
341 @include _menu-list-item-label-text-typography(
342 (
343 font: map.get($theme, menu-list-item-label-text-font),
344 line-height: map.get($theme, menu-list-item-label-text-line-height),
345 size: map.get($theme, menu-list-item-label-text-size),
346 tracking: map.get($theme, menu-list-item-label-text-tracking),
347 weight: map.get($theme, menu-list-item-label-text-weight),
348 )
349 );
350 @include _menu-list-item-selected-container-color(
351 map.get($theme, menu-list-item-selected-container-color)
352 );
353 @include _menu-list-item-with-leading-icon-leading-icon-color(
354 map.get($theme, menu-list-item-with-leading-icon-leading-icon-color)
355 );
356 @include _menu-list-item-with-leading-icon-leading-icon-size(
357 map.get($theme, menu-list-item-with-leading-icon-leading-icon-size)
358 );
359 // TODO: Create new mixin for trailing icon theming when select supports it.
360 @include _menu-list-item-with-leading-icon-leading-icon-color(
361 map.get($theme, menu-list-item-with-trailing-icon-trailing-icon-color)
362 );
363 @include _menu-list-item-with-leading-icon-leading-icon-size(
364 map.get($theme, menu-list-item-with-trailing-icon-trailing-icon-size)
365 );
366 @include bottom-line-color(
367 (
368 default: map.get($theme, text-field-active-indicator-color),
369 hover: map.get($theme, text-field-hover-active-indicator-color),
370 focus: map.get($theme, text-field-focus-active-indicator-color),
371 disabled: map.get($theme, text-field-disabled-indicator-color),
372 )
373 );
374 @include _text-field-error-active-indicator-color(
375 (
376 default: map.get($theme, text-field-error-active-indicator-color),
377 hover: map.get($theme, text-field-error-hover-active-indicator-color),
378 focus: map.get($theme, text-field-error-focus-active-indicator-color),
379 )
380 );
381 @include _text-field-active-indicator-height(
382 map.get($theme, text-field-active-indicator-height)
383 );
384 @include _text-field-caret-color(
385 (
386 default: map.get($theme, text-field-caret-color),
387 hover: map.get($theme, text-field-hover-caret-color),
388 focus: map.get($theme, text-field-focus-caret-color),
389 )
390 );
391 @include _text-field-error-caret-color(
392 (
393 default: map.get($theme, text-field-error-caret-color),
394 hover: map.get($theme, text-field-error-hover-caret-color),
395 focus: map.get($theme, text-field-error-focus-caret-color),
396 )
397 );
398 @include ink-color(
399 (
400 default: map.get($theme, text-field-input-text-color),
401 hover: map.get($theme, text-field-hover-input-text-color),
402 focus: map.get($theme, text-field-focus-input-text-color),
403 disabled: map.get($theme, text-field-disabled-input-text-color),
404 )
405 );
406 @include _error-input-text-color(
407 (
408 default: map.get($theme, text-field-error-input-text-color),
409 hover: map.get($theme, text-field-error-hover-input-text-color),
410 focus: map.get($theme, text-field-error-focus-input-text-color),
411 )
412 );
413 @include label-color(
414 (
415 default: map.get($theme, text-field-label-text-color),
416 hover: map.get($theme, text-field-hover-label-text-color),
417 focus: map.get($theme, text-field-focus-label-text-color),
418 disabled: map.get($theme, text-field-disabled-label-text-color),
419 )
420 );
421 @include label-floating-color(
422 (
423 default: map.get($theme, text-field-label-text-color),
424 hover: map.get($theme, text-field-hover-label-text-color),
425 focus: map.get($theme, text-field-focus-label-text-color),
426 disabled: map.get($theme, text-field-disabled-label-text-color),
427 )
428 );
429 @include _error-label-text-color(
430 (
431 default: map.get($theme, text-field-error-label-text-color),
432 hover: map.get($theme, text-field-error-hover-label-text-color),
433 focus: map.get($theme, text-field-error-focus-label-text-color),
434 )
435 );
436 @include _text-field-leading-icon-color(
437 (
438 default: map.get($theme, text-field-leading-icon-color),
439 hover: map.get($theme, text-field-hover-leading-icon-color),
440 focus: map.get($theme, text-field-focus-leading-icon-color),
441 disabled: map.get($theme, text-field-disabled-leading-icon-color),
442 )
443 );
444 @include _error-text-field-leading-icon-color(
445 (
446 default: map.get($theme, text-field-error-leading-icon-color),
447 hover: map.get($theme, text-field-error-hover-leading-icon-color),
448 focus: map.get($theme, text-field-error-focus-leading-icon-color),
449 )
450 );
451 @include select-helper-text-theme.helper-text-color(
452 (
453 default: map.get($theme, text-field-supporting-text-color),
454 disabled: map.get($theme, text-field-disabled-supporting-text-color),
455 )
456 );
457 @include select-helper-text-theme.helper-text-validation-color(
458 map.get($theme, text-field-error-supporting-text-color)
459 );
460 @include _text-field-input-text-typography(
461 (
462 font: map.get($theme, text-field-input-text-font),
463 line-height: map.get($theme, text-field-input-text-line-height),
464 size: map.get($theme, text-field-input-text-size),
465 tracking: map.get($theme, text-field-input-text-tracking),
466 weight: map.get($theme, text-field-input-text-weight),
467 )
468 );
469 @include _text-field-label-text-typography(
470 (
471 font: map.get($theme, text-field-label-text-font),
472 line-height: map.get($theme, text-field-label-text-line-height),
473 size: map.get($theme, text-field-label-text-size),
474 tracking: map.get($theme, text-field-label-text-tracking),
475 weight: map.get($theme, text-field-label-text-weight),
476 )
477 );
478 @include _text-field-label-text-populated-typography(
479 (
480 line-height: map.get($theme, text-field-label-text-populated-line-height),
481 size: map.get($theme, text-field-label-text-populated-size),
482 )
483 );
484 @include _text-field-supporting-text-typography(
485 (
486 font: map.get($theme, text-field-supporting-text-font),
487 line-height: map.get($theme, text-field-supporting-text-line-height),
488 size: map.get($theme, text-field-supporting-text-size),
489 tracking: map.get($theme, text-field-supporting-text-tracking),
490 weight: map.get($theme, text-field-supporting-text-weight),
491 )
492 );
493}
494
495@mixin _text-field-supporting-text-typography($typography-theme) {
496 & + .mdc-select-helper-text {
497 @include typography.theme-styles($typography-theme);
498 }
499}
500
501@mixin _text-field-input-text-typography($typography-theme) {
502 .mdc-select__selected-text {
503 @include typography.theme-styles($typography-theme);
504 }
505}
506
507@mixin _text-field-label-text-populated-typography($typography-theme) {
508 .mdc-floating-label--float-above,
509 // Used for CSS specificity to match with selector used in `outlined-height()`.
510 &.mdc-select--with-leading-icon .mdc-select__anchor .mdc-notched-outline .mdc-floating-label.mdc-floating-label--float-above {
511 @include typography.theme-styles($typography-theme);
512 }
513}
514
515@mixin _text-field-label-text-typography($typography-theme) {
516 .mdc-floating-label {
517 @include typography.theme-styles($typography-theme);
518 }
519}
520
521@mixin _error-outline-color($color) {
522 &.mdc-select--invalid {
523 @include outline-color($color);
524 }
525}
526
527@mixin _error-text-field-leading-icon-color($color) {
528 &.mdc-select--invalid {
529 @include _text-field-leading-icon-color($color);
530 }
531}
532
533@mixin _text-field-leading-icon-color($color) {
534 @include _if-enabled {
535 @include _set-text-field-leading-icon-color(
536 state.get-default-state($color)
537 );
538
539 &:not(.mdc-select--focused):hover {
540 @include _set-text-field-leading-icon-color(
541 state.get-hover-state($color)
542 );
543 }
544
545 @include _if-focused {
546 @include _set-text-field-leading-icon-color(
547 state.get-focus-state($color)
548 );
549 }
550 }
551
552 @include _if-disabled {
553 @include _set-text-field-leading-icon-color(
554 state.get-disabled-state($color)
555 );
556 }
557}
558
559@mixin _set-text-field-leading-icon-color($color) {
560 .mdc-select__anchor .mdc-select__icon {
561 @include theme.property(color, $color);
562 }
563}
564
565@mixin _error-label-text-color($color) {
566 &.mdc-select--invalid {
567 @include label-floating-color($color);
568 }
569}
570
571@mixin _error-input-text-color($color) {
572 &.mdc-select--invalid {
573 @include ink-color($color);
574 }
575}
576
577@mixin _text-field-caret-color($color) {
578 @include dropdown-icon-color($color);
579}
580
581@mixin _text-field-error-caret-color($color) {
582 &.mdc-select--invalid {
583 @include dropdown-icon-color($color);
584 }
585}
586
587@mixin _text-field-error-active-indicator-color($color) {
588 &.mdc-select--invalid {
589 @include bottom-line-color($color);
590 }
591}
592
593@mixin _text-field-active-indicator-height($height) {
594 .mdc-line-ripple {
595 @include line-ripple-mixins.height($height);
596 }
597}
598
599@mixin _menu-list-item-with-leading-icon-leading-icon-color($color) {
600 &:not(.mdc-select--disabled) .mdc-select__option .mdc-select__icon {
601 @include theme.property(color, $color);
602 }
603}
604
605@mixin _menu-list-item-with-leading-icon-leading-icon-size($size) {
606 &:not(.mdc-select--disabled) .mdc-select__option .mdc-select__icon {
607 @include theme.property(font-size, $size);
608 }
609}
610
611@mixin _menu-list-item-selected-container-color($color) {
612 .mdc-select__option {
613 @include list-evolution-mixins.list-item-selected-container-color($color);
614 }
615}
616
617@mixin _menu-list-item-label-text-typography($typography-theme) {
618 .mdc-select__option {
619 @include list-evolution-mixins.list-primary-text-typography(
620 $typography-theme
621 );
622 }
623}
624
625@mixin _menu-list-item-label-text-color($color) {
626 .mdc-select__option {
627 @include list-evolution-mixins.list-primary-text-ink-color($color);
628 }
629}
630
631@mixin _menu-list-item-container-height($height) {
632 .mdc-select__option {
633 @include list-evolution-mixins.list-item-height($height);
634 }
635}
636
637@mixin _menu-divider-color($color) {
638 .mdc-select__list {
639 @include list-evolution-mixins.divider-color($color);
640 }
641}
642
643@mixin _menu-divider-height($height) {
644 .mdc-select__list {
645 @include list-evolution-mixins.divider-height($height);
646 }
647}
648
649@mixin _menu-container-color($color) {
650 .mdc-select__menu {
651 @include menu-surface-mixins.fill-color($color);
652 }
653}
654
655@mixin _menu-container-elevation($resolver, $shadow-color, $elevation) {
656 .mdc-select__menu {
657 @include elevation-theme.with-resolver(
658 $resolver,
659 $elevation: $elevation,
660 $shadow-color: $shadow-color
661 );
662 }
663}
664
665@mixin _menu-container-shape($shape) {
666 .mdc-select__menu {
667 @include menu-surface-mixins.shape-radius($shape);
668 }
669}
670
671@mixin menu-list-item-secondary-label-text-color($color) {
672 .mdc-select__list {
673 @include list-evolution-mixins.list-secondary-text-ink-color($color);
674 }
675}
676
677@mixin menu-list-item-secondary-label-text-typography($typography-theme) {
678 .mdc-select__list {
679 @include list-evolution-mixins.list-secondary-text-typography(
680 $typography-theme
681 );
682 }
683}
684
685/// Sets the min-width of the select.
686/// @param {Number} $min-width - The desired min-width.
687/// @deprecated using this mixin is no longer required, and clients may set
688/// the attribute directly
689@mixin min-width($min-width, $query: feature-targeting.all()) {
690 $feat-structure: feature-targeting.create-target($query, structure);
691
692 @include feature-targeting.targets($feat-structure) {
693 min-width: $min-width;
694 }
695}
696
697/// Sets the select behavior to change width dynamically based on content.
698/// @param {Number} $min-width - The min-width of the select, which should be
699/// large enough to allow the label (if exists) to display in full.
700@mixin variable-width($min-width, $query: feature-targeting.all()) {
701 $feat-structure: feature-targeting.create-target($query, structure);
702
703 .mdc-select__anchor {
704 @include feature-targeting.targets($feat-structure) {
705 width: 100%;
706 min-width: $min-width;
707 }
708 }
709}
710
711@mixin ink-color($color-or-map, $query: feature-targeting.all()) {
712 @include _if-enabled {
713 @include _ink-color(state.get-default-state($color-or-map), $query: $query);
714 }
715
716 @include _if-disabled {
717 @include _ink-color(
718 state.get-disabled-state($color-or-map),
719 $query: $query
720 );
721 }
722}
723
724@mixin container-fill-color($color-or-map, $query: feature-targeting.all()) {
725 @include _if-enabled {
726 @include _container-fill-color(
727 state.get-default-state($color-or-map),
728 $query: $query
729 );
730 }
731
732 @include _if-disabled {
733 @include _container-fill-color(
734 state.get-disabled-state($color-or-map),
735 $query: $query
736 );
737 }
738}
739
740@mixin dropdown-icon-color($color-or-map, $query: feature-targeting.all()) {
741 @include _if-enabled {
742 @include _dropdown-icon-color(
743 state.get-default-state($color-or-map),
744 $query: $query
745 );
746
747 &:not(.mdc-select--focused):hover {
748 @include _dropdown-icon-color(
749 state.get-hover-state($color-or-map),
750 $query: $query
751 );
752 }
753
754 @include _if-focused {
755 @include _dropdown-icon-color(
756 state.get-focus-state($color-or-map),
757 $query: $query
758 );
759 }
760 }
761
762 @include _if-disabled {
763 @include _dropdown-icon-color(
764 state.get-disabled-state($color-or-map),
765 $query: $query
766 );
767 }
768}
769
770@mixin label-floating-color($color-or-map, $query: feature-targeting.all()) {
771 @include _if-enabled {
772 @include _label-floating-color(
773 state.get-default-state($color-or-map),
774 $query: $query
775 );
776
777 &:not(.mdc-select--focused):hover {
778 @include _label-floating-color(
779 state.get-hover-state($color-or-map),
780 $query: $query
781 );
782 }
783 }
784}
785
786@mixin bottom-line-color($color-or-map, $query: feature-targeting.all()) {
787 @include _if-enabled {
788 @include _bottom-line-color(
789 state.get-default-state($color-or-map),
790 $query: $query
791 );
792
793 // bottom line inactive/active are on different elements, does not need
794 // to check for :not() focused
795 &:hover {
796 @include _bottom-line-color(
797 state.get-hover-state($color-or-map),
798 $query: $query
799 );
800 }
801
802 @include _focused-line-ripple-color(
803 state.get-focus-state($color-or-map),
804 $query: $query
805 );
806 }
807
808 @include _if-disabled {
809 @include _bottom-line-color(
810 state.get-disabled-state($color-or-map),
811 $query: $query
812 );
813 }
814}
815
816@mixin label-color($color-or-map, $query: feature-targeting.all()) {
817 @include _if-enabled {
818 @include _label-color(
819 state.get-default-state($color-or-map),
820 $query: $query
821 );
822
823 @include _if-focused {
824 @include _label-color(
825 state.get-focus-state($color-or-map),
826 $query: $query
827 );
828 }
829
830 &:not(.mdc-select--focused):hover {
831 @include _label-color(
832 state.get-hover-state($color-or-map),
833 $query: $query
834 );
835 }
836 }
837
838 @include _if-disabled {
839 @include _label-color(
840 state.get-disabled-state($color-or-map),
841 $query: $query
842 );
843 }
844}
845
846@mixin outline-color($color-or-map, $query: feature-targeting.all()) {
847 @include _if-enabled {
848 @include _outline-color(
849 state.get-default-state($color-or-map),
850 $query: $query
851 );
852
853 &:not(.mdc-select--focused) .mdc-select__anchor:hover {
854 @include _hover-outline-color(
855 state.get-hover-state($color-or-map),
856 $query: $query
857 );
858 }
859
860 @include _if-focused {
861 @include _focused-outline-color(
862 state.get-focus-state($color-or-map),
863 $query: $query
864 );
865 }
866 }
867
868 @include _if-disabled {
869 @include _outline-color(
870 state.get-disabled-state($color-or-map),
871 $query: $query
872 );
873 }
874}
875
876@mixin outline-width($width) {
877 @include _if-enabled {
878 @include _outline-width(state.get-default-state($width));
879
880 &:not(.mdc-select--focused) .mdc-select__anchor:hover {
881 @include _outline-width(state.get-hover-state($width));
882 }
883
884 @include _if-focused {
885 .mdc-notched-outline {
886 @include _outline-width(state.get-focus-state($width));
887 }
888 }
889 }
890}
891
892@mixin _outline-width($width) {
893 @if $width {
894 @include notched-outline-mixins.stroke-width($width);
895 }
896}
897
898///
899/// Sets the dropdown icon to the specified size.
900///
901@mixin dropdown-icon-size($size, $query: feature-targeting.all()) {
902 $feat-structure: feature-targeting.create-target($query, structure);
903
904 .mdc-select__dropdown-icon {
905 @include feature-targeting.targets($feat-structure) {
906 width: $size;
907 height: $size;
908 }
909 }
910}
911
912@mixin filled-shape-radius(
913 $radius,
914 $density-scale: $density-scale,
915 $rtl-reflexive: false,
916 $query: feature-targeting.all()
917) {
918 @if meta.type-of($radius) == 'list' and list.length($radius) > 2 {
919 @error "mdc-select: Invalid radius #{$radius}. Only top-left and top-right corners may be customized.";
920 }
921
922 $height: density-functions.prop-value(
923 $density-config: $density-config,
924 $density-scale: $density-scale,
925 $property-name: height,
926 );
927
928 $masked-radius: shape-functions.mask-radius($radius, 1 1 0 0);
929
930 .mdc-select__anchor {
931 @include shape-mixins.radius(
932 $masked-radius,
933 $rtl-reflexive,
934 $component-height: $height,
935 $query: $query
936 );
937 }
938}
939
940@mixin outline-shape-radius(
941 $radius,
942 $density-scale: $density-scale,
943 $rtl-reflexive: false,
944 $query: feature-targeting.all(),
945 $height: null
946) {
947 $feat-structure: feature-targeting.create-target($query, structure);
948
949 @if not $height {
950 $height: density-functions.prop-value(
951 $density-config: $density-config,
952 $density-scale: $density-scale,
953 $property-name: height,
954 );
955 }
956
957 .mdc-notched-outline {
958 @include notched-outline-mixins.shape-radius(
959 $radius,
960 $rtl-reflexive,
961 $component-height: $height,
962 $query: $query
963 );
964 }
965
966 $resolved-radius: shape-functions.resolve-radius(
967 $radius,
968 $component-height: $height
969 );
970 $unpacked-radius: shape-functions.unpack-radius($resolved-radius);
971 $top-left-radius: list.nth($unpacked-radius, 1);
972 $top-left-is-custom-prop: custom-properties.is-custom-prop($top-left-radius);
973 $top-left-radius-px: $top-left-radius;
974 @if ($top-left-is-custom-prop) {
975 $top-left-radius-px: custom-properties.get-fallback($top-left-radius);
976 }
977
978 @if (
979 $top-left-is-custom-prop or
980 $top-left-radius-px >
981 notched-outline-variables.$leading-width
982 ) {
983 .mdc-select__anchor {
984 @include _apply-outline-shape-padding(
985 padding-left,
986 $top-left-radius,
987 $add-label-padding: true,
988 $query: $query
989 );
990
991 @include rtl.rtl {
992 @include feature-targeting.targets($feat-structure) {
993 @include rtl.ignore-next-line();
994 padding-left: 0;
995 }
996 @include _apply-outline-shape-padding(
997 padding-right,
998 $top-left-radius,
999 $add-label-padding: true,
1000 $query: $query
1001 );
1002 }
1003 }
1004
1005 + .mdc-select-helper-text {
1006 @include _apply-outline-shape-padding(
1007 margin-left,
1008 $top-left-radius,
1009 $add-label-padding: true,
1010 $query: $query
1011 );
1012
1013 @include rtl.rtl {
1014 @include feature-targeting.targets($feat-structure) {
1015 @include rtl.ignore-next-line();
1016 margin-left: 0;
1017 }
1018 @include _apply-outline-shape-padding(
1019 margin-right,
1020 $top-left-radius,
1021 $add-label-padding: true,
1022 $query: $query
1023 );
1024 }
1025 }
1026
1027 // Unlike textfield, select does not need to re-apply leading icon padding.
1028 // This is because select only has one potential leading class, not two
1029 // extra classes like textfield (leading + trailing). Textfield's two extra
1030 // classes can cause specificity conflicts, requiring everything to be
1031 // re-applied.
1032 }
1033}
1034
1035///
1036/// Sets density scale for filled select variant.
1037///
1038/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
1039/// `-3`, `-2`, `-1`, `0`. Default is `0`.
1040/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
1041/// filled selects at which to allow floating labels.
1042///
1043@mixin filled-density(
1044 $density-scale,
1045 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1046 $query: feature-targeting.all()
1047) {
1048 $height: density-functions.prop-value(
1049 $density-config: $density-config,
1050 $density-scale: $density-scale,
1051 $property-name: height,
1052 );
1053
1054 @include filled-height(
1055 $height,
1056 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1057 $query: $query
1058 );
1059 @include _list-density($density-scale, $query: $query);
1060}
1061
1062///
1063/// Sets density scale for filled select variant with leading icon.
1064///
1065/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
1066/// `-3`, `-2`, `-1`, `0`. Default is `0`.
1067/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
1068/// filled selects at which to allow floating labels.
1069///
1070@mixin filled-with-leading-icon-density(
1071 $density-scale,
1072 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1073 $query: feature-targeting.all()
1074) {
1075 $height: density-functions.prop-value(
1076 $density-config: $density-config,
1077 $density-scale: $density-scale,
1078 $property-name: height,
1079 );
1080
1081 @include filled-with-leading-icon-height(
1082 $height,
1083 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1084 $query: $query
1085 );
1086 @include _list-density($density-scale, $query: $query);
1087}
1088
1089///
1090/// Sets density scale for outlined select (Excluding outlined select with leading icon).
1091///
1092/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
1093/// `-3`, `-2`, `-1`, `0`. Default is `0`.
1094///
1095@mixin outlined-density($density-scale, $query: feature-targeting.all()) {
1096 $height: density-functions.prop-value(
1097 $density-config: $density-config,
1098 $density-scale: $density-scale,
1099 $property-name: height,
1100 );
1101
1102 @include outlined-height($height, $query: $query);
1103 @include _list-density($density-scale, $query: $query);
1104}
1105
1106///
1107/// Sets density scale for outlined select with leading icon.
1108///
1109/// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-4`,
1110/// `-3`, `-2`, `-1`, `0`. Default is `0`.
1111///
1112@mixin outlined-with-leading-icon-density(
1113 $density-scale,
1114 $query: feature-targeting.all()
1115) {
1116 $height: density-functions.prop-value(
1117 $density-config: $density-config,
1118 $density-scale: $density-scale,
1119 $property-name: height,
1120 );
1121
1122 @include outlined-with-leading-icon-height($height, $query: $query);
1123 @include _list-density($density-scale, $query: $query);
1124}
1125
1126@mixin _list-density($density-scale, $query) {
1127 @include list-mixins.deprecated-single-line-density(
1128 $density-scale,
1129 $query: $query
1130 );
1131 .mdc-select__one-line-option {
1132 @include list-evolution-mixins.one-line-item-density(
1133 $density-scale,
1134 $exclude-variants: true,
1135 $query: $query
1136 );
1137 }
1138 .mdc-select__two-line-option {
1139 @include list-evolution-mixins.two-line-item-density(
1140 $density-scale,
1141 $query: $query
1142 );
1143 }
1144}
1145
1146///
1147/// Sets height of default select variant.
1148///
1149/// @param {Number} $new-height
1150/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
1151/// filled selects at which to allow floating labels.
1152/// @param {Number} $filled-baseline-top The baseline from the top of the anchor
1153/// that the input should be aligned to for a filled variant with a label
1154/// @access public
1155///
1156@mixin filled-height(
1157 $new-height,
1158 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1159 $filled-baseline-top: $filled-baseline-top,
1160 $query: feature-targeting.all()
1161) {
1162 $feat-structure: feature-targeting.create-target($query, structure);
1163
1164 .mdc-select__anchor {
1165 @include feature-targeting.targets($feat-structure) {
1166 height: $new-height;
1167 }
1168
1169 // Filled variant is aligned to baseline...
1170 @include typography-mixins.baseline(
1171 $top: $filled-baseline-top,
1172 $display: flex,
1173 $query: $query
1174 );
1175 // ...unless it is too small to display a label
1176 @if $new-height < $minimum-height-for-filled-label {
1177 @include center-aligned($query: $query);
1178
1179 @include feature-targeting.targets($feat-structure) {
1180 .mdc-floating-label {
1181 display: none;
1182 }
1183 }
1184 }
1185 }
1186
1187 // No-label variants are always centered
1188 &.mdc-select--no-label .mdc-select__anchor {
1189 @include center-aligned($query: $query);
1190 }
1191
1192 @if $new-height < $height {
1193 @include dropdown-icon-size(
1194 select-icon-theme.$dense-icon-size,
1195 $query: $query
1196 );
1197
1198 &.mdc-select--filled {
1199 @include truncate-floating-label-max-width(
1200 $leading-icon-size: 0,
1201 $dropdown-icon-size: select-icon-theme.$dense-icon-size,
1202 $query: $query
1203 );
1204 }
1205 }
1206}
1207
1208///
1209/// Sets height of filled select variant with leading icon.
1210///
1211/// @param {Number} $height
1212/// @param {Number} $minimum-height-for-filled-label Sets the minimum height for
1213/// filled selects at which to allow floating labels.
1214/// @param {Number} $filled-baseline-top The baseline from the top of the anchor
1215/// that the input should be aligned to for a filled variant with a label
1216/// @access public
1217///
1218@mixin filled-with-leading-icon-height(
1219 $new-height,
1220 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1221 $filled-baseline-top: $filled-baseline-top,
1222 $query: feature-targeting.all()
1223) {
1224 $feat-structure: feature-targeting.create-target($query, structure);
1225
1226 @include filled-height(
1227 $new-height,
1228 $minimum-height-for-filled-label: $minimum-height-for-filled-label,
1229 $filled-baseline-top: $filled-baseline-top,
1230 $query: $query
1231 );
1232
1233 @if $new-height < $height {
1234 @include select-icon-theme.size(
1235 select-icon-theme.$dense-icon-size,
1236 $query: $query
1237 );
1238
1239 &.mdc-select--filled {
1240 @include truncate-floating-label-max-width(
1241 $leading-icon-size: select-icon-theme.$dense-icon-size,
1242 $dropdown-icon-size: select-icon-theme.$dense-icon-size,
1243 $query: $query
1244 );
1245 }
1246
1247 .mdc-deprecated-list-item__graphic {
1248 width: select-icon-theme.$dense-icon-size;
1249 height: select-icon-theme.$dense-icon-size;
1250 }
1251
1252 @include list-evolution-mixins.item-start-size(
1253 $width: select-icon-theme.$dense-icon-size + 12px,
1254 $height: select-icon-theme.$dense-icon-size,
1255 $query: $query
1256 );
1257
1258 .mdc-select__anchor {
1259 @include leading-icon-floating-label-position(
1260 select-icon-theme.$dense-icon-size,
1261 $query: $query
1262 );
1263 }
1264 }
1265}
1266
1267///
1268/// Sets height of outlined select variant (Excluding outlined select with leading icon).
1269///
1270/// @param {Number} $new-height
1271/// @param {String} $keyframe-suffix - Optional suffix to use for generated
1272/// floating label keyframes
1273///
1274@mixin outlined-height(
1275 $new-height,
1276 $keyframe-suffix: select-outlined-#{$new-height},
1277 $query: feature-targeting.all()
1278) {
1279 $feat-structure: feature-targeting.create-target($query, structure);
1280 $positionY: get-outlined-label-position-y($new-height);
1281
1282 .mdc-select__anchor {
1283 // Floating label position
1284 @include notched-outline-mixins.floating-label-float-position-absolute(
1285 $positionY,
1286 $query: $query
1287 );
1288
1289 // Floating label animation
1290 @include floating-label-mixins.shake-animation(
1291 $keyframe-suffix,
1292 $query: $query
1293 );
1294 @at-root {
1295 @include floating-label-mixins.shake-keyframes(
1296 $keyframe-suffix,
1297 $positionY,
1298 $query: $query
1299 );
1300 }
1301
1302 @include feature-targeting.targets($feat-structure) {
1303 height: $new-height;
1304 }
1305 }
1306
1307 @if $new-height < $height {
1308 @include dropdown-icon-size(
1309 select-icon-theme.$dense-icon-size,
1310 $query: $query
1311 );
1312
1313 &.mdc-select--outlined {
1314 @include truncate-notched-outline-max-width(
1315 $leading-icon-size: 0,
1316 $dropdown-icon-size: select-icon-theme.$dense-icon-size,
1317 $query: $query
1318 );
1319 }
1320 }
1321}
1322
1323///
1324/// Sets height of outlined select with leading icon variant.
1325///
1326/// @param {Number} $new-height
1327/// @param {String} $keyframe-suffix - Optional suffix to use for generated
1328/// floating label keyframes
1329///
1330@mixin outlined-with-leading-icon-height(
1331 $new-height,
1332 $keyframe-suffix: null,
1333 $query: feature-targeting.all()
1334) {
1335 $feat-structure: feature-targeting.create-target($query, structure);
1336
1337 .mdc-select__anchor {
1338 @if $new-height < $height {
1339 @include dropdown-icon-size(
1340 select-icon-theme.$dense-icon-size,
1341 $query: $query
1342 );
1343 @include outlined-with-leading-icon-floating-label-position-animation(
1344 $new-height,
1345 select-icon-theme.$dense-icon-size,
1346 $keyframe-suffix,
1347 $query: $query
1348 );
1349 } @else {
1350 @include outlined-with-leading-icon-floating-label-position-animation(
1351 $new-height,
1352 select-icon-theme.$icon-size,
1353 $keyframe-suffix,
1354 $query: $query
1355 );
1356 }
1357
1358 @include feature-targeting.targets($feat-structure) {
1359 height: $new-height;
1360 }
1361 }
1362
1363 @if $new-height < $height {
1364 .mdc-deprecated-list-item__graphic {
1365 width: select-icon-theme.$dense-icon-size;
1366 height: select-icon-theme.$dense-icon-size;
1367 }
1368
1369 @include list-evolution-mixins.item-start-size(
1370 $width: select-icon-theme.$dense-icon-size + 12px,
1371 $height: select-icon-theme.$dense-icon-size,
1372 $query: $query
1373 );
1374
1375 @include select-icon-theme.size(
1376 select-icon-theme.$dense-icon-size,
1377 $query: $query
1378 );
1379
1380 &.mdc-select--outlined {
1381 @include truncate-notched-outline-max-width(
1382 $leading-icon-size: select-icon-theme.$dense-icon-size,
1383 $dropdown-icon-size: select-icon-theme.$dense-icon-size,
1384 $query: $query
1385 );
1386 }
1387 }
1388}
1389
1390// $add-label-padding is copied from textfield's mixin, even though select
1391// always sets it to true. This is to try and keep things aligned between select
1392// and textfield for when these styles are refactored into shared styles.
1393@mixin _apply-outline-shape-padding(
1394 $property,
1395 $padding,
1396 $add-label-padding: false,
1397 $query: feature-targeting.all()
1398) {
1399 $feat-structure: feature-targeting.create-target($query, structure);
1400 $padding-is-custom-prop: custom-properties.is-custom-prop($padding);
1401 $padding-px: $padding;
1402 @if ($padding-is-custom-prop) {
1403 $padding-px: custom-properties.get-fallback($padding);
1404 }
1405
1406 @include feature-targeting.targets($feat-structure) {
1407 // The shape should only change the padding if the radius becomes greater
1408 // than the default padding. That means we need to add more padding.
1409 @if ($padding-px > notched-outline-variables.$leading-width) {
1410 // Set a px value if it's greater. This is either the only value (if
1411 // we're given an exact value), or an IE11 fallback if we're given a
1412 // custom property and the fallback value is greater than the padding.
1413 $value: $padding-px;
1414 @if ($add-label-padding) {
1415 // If this is for the top-left leading, add the notched outline padding
1416 // to keep it aligned with the label
1417 $value: $padding-px + notched-outline-variables.$padding;
1418 }
1419
1420 @include rtl.ignore-next-line();
1421 #{$property}: $value;
1422 @include gss.annotate(
1423 (
1424 alternate: $padding-is-custom-prop,
1425 )
1426 );
1427 }
1428 @if ($padding-is-custom-prop) {
1429 // If it's a custom property, always add it since the value may change
1430 // to be greater than the padding at runtime, even if the fallback is
1431 // not currently greater than the default padding.
1432 $value: custom-properties.create-var($padding);
1433 @if ($add-label-padding) {
1434 $value: calc(#{$value} + #{notched-outline-variables.$padding});
1435 }
1436
1437 // Interpolation is a workaround for sass/sass#3259.
1438 @supports (top: max(#{0%})) {
1439 // A max() function makes this runtime dynamic. The padding will be
1440 // whichever is greater: the default horizontal padding, or the
1441 // calculated custom property plus extra padding.
1442 @include rtl.ignore-next-line();
1443 #{$property}: max(#{$anchor-padding-left}, #{$value});
1444 }
1445 }
1446 }
1447}
1448
1449// Removes filled baseline alignment
1450@mixin center-aligned($query: feature-targeting.all()) {
1451 $feat-structure: feature-targeting.create-target($query, structure);
1452
1453 .mdc-select__selected-text {
1454 @include typography-mixins.zero-width-prefix($query: $query);
1455 }
1456
1457 @include feature-targeting.targets($feat-structure) {
1458 // In order for a flexbox container to participate in baseline alignment,
1459 // it follows these rules to determine where its baseline is:
1460 // https://www.w3.org/TR/css-flexbox-1/#flex-baselines
1461 //
1462 // In order to avoid leading icons "controlling" the baseline (since they
1463 // are the first child), flexbox will generate a baseline from any child
1464 // flex items that participate in baseline alignment.
1465 //
1466 // Icons are set to "align-self: center", while all other children are
1467 // aligned to baseline. The next problem is deciding which child is
1468 // used to determine the baseline.
1469 //
1470 // According to spec, the item with the largest distance between its
1471 // baseline and the edge of the cross axis is placed flush with that edge,
1472 // making it the baseline of the container.
1473 // https://www.w3.org/TR/css-flexbox-1/#baseline-participation
1474 //
1475 // For the filled variant, the pseudo ::before strut is the "largest"
1476 // child since the input has a height of 28px and the strut is 40px. We
1477 // can emulate center alignment and force the baseline to use the input
1478 // text by making the input the full height of the container and removing
1479 // the baseline strut.
1480 //
1481 // IE11 does not respect this, and makes the leading icon (if present)
1482 // the baseline.
1483 .mdc-select__selected-text-container {
1484 height: 100%;
1485 display: inline-flex;
1486 align-items: center;
1487 }
1488
1489 &::before {
1490 display: none;
1491 }
1492 }
1493}
1494
1495///
1496/// Sets the position of the floating label for a select with leading icon.
1497/// @param {number} $icon-size - The size of the leading icon.
1498///
1499@mixin leading-icon-floating-label-position(
1500 $icon-size: select-icon-theme.$icon-size,
1501 $query: feature-targeting.all()
1502) {
1503 $feat-structure: feature-targeting.create-target($query, structure);
1504 $icon-total-width: $icon-size + 2 * select-icon-theme.$icon-horizontal-margin;
1505
1506 .mdc-floating-label {
1507 @include feature-targeting.targets($feat-structure) {
1508 @include rtl.reflexive-position(left, $icon-total-width);
1509 }
1510 }
1511}
1512
1513///
1514/// Sets the floating label position and animations for a given height for an
1515/// outlined select with leaing icon.
1516/// @param {number} $icon-size - The size of the leading icon.
1517/// @param {string} $keyframe-suffix - The suffix for the newly generated keyframes.
1518///
1519@mixin outlined-with-leading-icon-floating-label-position-animation(
1520 $height,
1521 $icon-size,
1522 $keyframe-suffix: select-outlined-leading-icon-#{$height},
1523 $query: feature-targeting.all()
1524) {
1525 $feat-structure: feature-targeting.create-target($query, structure);
1526
1527 $icon-total-width: $icon-size + 2 * select-icon-theme.$icon-horizontal-margin;
1528 $resting-position-x: $icon-total-width -
1529 select-icon-theme.$icon-horizontal-margin;
1530 $float-position-y: get-outlined-label-position-y($height);
1531 $float-position-x: $icon-size + select-icon-theme.$icon-horizontal-margin -
1532 notched-outline-variables.$notch-gutter-size;
1533
1534 // Resting label position
1535 .mdc-floating-label {
1536 @include feature-targeting.targets($feat-structure) {
1537 @include rtl.reflexive-position(left, $resting-position-x);
1538 }
1539 }
1540
1541 // Floating label position
1542 @include notched-outline-mixins.floating-label-float-position-absolute(
1543 $float-position-y,
1544 $float-position-x,
1545 $query: $query
1546 );
1547
1548 // Floating label animation
1549 @include floating-label-mixins.shake-animation(
1550 $keyframe-suffix,
1551 $query: $query
1552 );
1553 @at-root {
1554 @include floating-label-mixins.shake-keyframes(
1555 $keyframe-suffix,
1556 $float-position-y,
1557 $float-position-x,
1558 $query: $query
1559 );
1560 }
1561
1562 $keyframe-suffix-rtl: #{$keyframe-suffix}-rtl;
1563 @include rtl.rtl {
1564 @include floating-label-mixins.shake-animation(
1565 $keyframe-suffix,
1566 $query: $query
1567 );
1568 }
1569 @at-root {
1570 @include floating-label-mixins.shake-keyframes(
1571 $keyframe-suffix-rtl,
1572 $float-position-y,
1573 -($float-position-x),
1574 $query: $query
1575 );
1576 }
1577}
1578
1579///
1580/// Truncates the max-width of the floating label according to sizes of the
1581/// leading icon and dropdown icon.
1582///
1583/// @param {Number} $leading-icon-size - Size of leading icon.
1584/// @param {Number} $dropdown-icon-size - Size of dropdown icon.
1585///
1586@mixin truncate-floating-label-max-width(
1587 $leading-icon-size,
1588 $dropdown-icon-size,
1589 $query: feature-targeting.all()
1590) {
1591 $truncation: select-icon-theme.$icon-horizontal-margin * 2 +
1592 $dropdown-icon-size;
1593
1594 @if $leading-icon-size > 0 {
1595 $truncation: $truncation +
1596 select-icon-theme.$icon-horizontal-margin *
1597 2 +
1598 $leading-icon-size;
1599 } @else {
1600 $truncation: $truncation + $outline-label-offset;
1601 }
1602
1603 .mdc-floating-label {
1604 @include floating-label-mixins.max-width(
1605 calc(100% - #{$truncation}),
1606 $query: $query
1607 );
1608 }
1609
1610 .mdc-floating-label--float-above {
1611 $scale: floating-label-variables.$float-scale;
1612 @include floating-label-mixins.max-width(
1613 calc(100% / #{$scale} - #{$truncation} / #{$scale}),
1614 $query: $query
1615 );
1616 }
1617}
1618
1619///
1620/// Truncates the max-width of the notched outline according to the sizes of
1621/// the leading icon and dropdown icon.
1622///
1623/// @param {Number} $leading-icon-size - Size of leading icon.
1624/// @param {Number} $dropdown-icon-size - Size of dropdown icon.
1625///
1626@mixin truncate-notched-outline-max-width(
1627 $leading-icon-size,
1628 $dropdown-icon-size,
1629 $query: feature-targeting.all()
1630) {
1631 $truncation: select-icon-theme.$icon-horizontal-margin * 2 +
1632 $dropdown-icon-size + notched-outline-variables.$leading-width;
1633
1634 @if $leading-icon-size > 0 {
1635 $truncation: $truncation +
1636 select-icon-theme.$icon-horizontal-margin +
1637 $leading-icon-size;
1638 }
1639 .mdc-select__anchor {
1640 @include notched-outline-mixins.notch-max-width(
1641 calc(100% - #{$truncation}),
1642 $query: $query
1643 );
1644 }
1645}
1646
1647/// Selector for focused state
1648/// @access private
1649@mixin _if-focused {
1650 &.mdc-select--focused {
1651 @content;
1652 }
1653}
1654
1655/// Selector for enabled state
1656/// @access private
1657@mixin _if-enabled {
1658 &:not(.mdc-select--disabled) {
1659 @content;
1660 }
1661}
1662
1663/// Selector for disabled state
1664/// @access private
1665@mixin _if-disabled {
1666 &.mdc-select--disabled {
1667 @content;
1668 }
1669}
1670
1671@mixin _ink-color($color, $query: feature-targeting.all()) {
1672 $feat-color: feature-targeting.create-target($query, color);
1673
1674 @if $color {
1675 .mdc-select__selected-text {
1676 @include feature-targeting.targets($feat-color) {
1677 @include theme-mixins.property(color, $color);
1678 }
1679 }
1680 }
1681}
1682
1683@mixin _container-fill-color($color, $query: feature-targeting.all()) {
1684 $feat-color: feature-targeting.create-target($query, color);
1685
1686 @if $color {
1687 .mdc-select__anchor {
1688 @include feature-targeting.targets($feat-color) {
1689 @include theme-mixins.property(background-color, $color);
1690 }
1691 }
1692 }
1693}
1694
1695@mixin _bottom-line-color($color, $query: feature-targeting.all()) {
1696 @if $color {
1697 .mdc-line-ripple {
1698 @include line-ripple-mixins.inactive-color($color, $query: $query);
1699 }
1700 }
1701}
1702
1703@mixin _focused-line-ripple-color($color, $query: feature-targeting.all()) {
1704 @if $color {
1705 .mdc-line-ripple {
1706 @include line-ripple-mixins.active-color($color, $query: $query);
1707 }
1708 }
1709}
1710
1711@mixin _outline-color($color, $query: feature-targeting.all()) {
1712 @if $color {
1713 @include notched-outline-mixins.color($color, $query: $query);
1714 }
1715}
1716
1717@mixin _hover-outline-color($color, $query: feature-targeting.all()) {
1718 @if $color {
1719 .mdc-notched-outline {
1720 @include notched-outline-mixins.color($color, $query: $query);
1721 }
1722 }
1723}
1724
1725@mixin _focused-outline-color($color, $query: feature-targeting.all()) {
1726 @if $color {
1727 .mdc-notched-outline {
1728 @include notched-outline-mixins.stroke-width(
1729 $outlined-stroke-width,
1730 $query: $query
1731 );
1732 @include notched-outline-mixins.color($color, $query: $query);
1733 }
1734 }
1735}
1736
1737@mixin _label-color($color, $query: feature-targeting.all()) {
1738 @if $color {
1739 .mdc-floating-label {
1740 @include floating-label-mixins.ink-color($color, $query: $query);
1741 }
1742 }
1743}
1744
1745@mixin _label-floating-color($color, $query: feature-targeting.all()) {
1746 @if $color {
1747 .mdc-floating-label--float-above {
1748 @include floating-label-mixins.ink-color($color, $query: $query);
1749 }
1750 }
1751}
1752
1753///
1754/// Sets the dropdown icon to the specified color.
1755/// @access private
1756///
1757@mixin _dropdown-icon-color($color, $query: feature-targeting.all()) {
1758 $feat-color: feature-targeting.create-target($query, color);
1759
1760 @if $color {
1761 @include feature-targeting.targets($feat-color) {
1762 .mdc-select__dropdown-icon {
1763 @include theme-mixins.property(fill, $color);
1764 }
1765 }
1766 }
1767}