UNPKG

15.1 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 '@material/dom/mixins' as dom-mixins;
29@use '@material/feature-targeting/feature-targeting';
30@use '@material/floating-label/mixins' as floating-label-mixins;
31@use '@material/floating-label/variables' as floating-label-variables;
32@use '@material/list/mixins' as list-mixins;
33@use '@material/list/evolution-mixins' as list-evolution-mixins;
34@use '@material/notched-outline/mixins' as notched-outline-mixins;
35@use '@material/notched-outline/variables' as notched-outline-variables;
36@use '@material/rtl/rtl';
37@use '@material/theme/mixins' as theme-mixins;
38@use '@material/typography/mixins' as typography-mixins;
39@use './select-helper-text-theme';
40@use './select-icon-theme';
41@use './select-theme';
42@use './select-filled';
43@use './select-outlined';
44@use './select-ripple';
45@use './select-helper-text';
46@use './select-icon';
47
48@mixin core-styles($query: feature-targeting.all()) {
49 $feat-animation: feature-targeting.create-target($query, animation);
50 $feat-color: feature-targeting.create-target($query, color);
51 $feat-structure: feature-targeting.create-target($query, structure);
52
53 .mdc-select {
54 @include select-theme.ink-color(
55 (
56 default: select-theme.$ink-color,
57 disabled: select-theme.$disabled-ink-color,
58 ),
59 $query: $query
60 );
61
62 @include select-theme.label-color(
63 (
64 default: select-theme.$label-color,
65 focus: select-theme.$focused-label-color,
66 disabled: select-theme.$disabled-label-color,
67 ),
68 $query: $query
69 );
70
71 @include select-theme.dropdown-icon-color(
72 (
73 default: select-theme.$dropdown-icon-color,
74 focus: primary,
75 disabled: select-theme.$disabled-dropdown-icon-color,
76 ),
77 $query: $query
78 );
79
80 @include select-helper-text-theme.helper-text-color(
81 (
82 default: select-helper-text-theme.$helper-text-color,
83 disabled: select-helper-text-theme.$disabled-helper-text-color,
84 ),
85 $query: $query
86 );
87
88 @include select-icon-theme.icon-color(
89 (
90 default: select-icon-theme.$icon-color,
91 disabled: select-icon-theme.$disabled-icon-color,
92 ),
93 $query: $query
94 );
95
96 // High-contrast mode support
97 @include dom-mixins.forced-colors-mode() {
98 $gray-text: (
99 disabled: GrayText,
100 );
101 @include select-theme.ink-color($gray-text, $query: $query);
102 @include select-theme.dropdown-icon-color(
103 (
104 disabled: red,
105 ),
106 $query: $query
107 );
108 @include select-theme.label-color($gray-text, $query: $query);
109 @include select-theme.bottom-line-color($gray-text, $query: $query);
110 @include select-theme.outline-color($gray-text, $query: $query);
111 @include select-icon-theme.icon-color($gray-text, $query: $query);
112 @include select-helper-text-theme.helper-text-color(
113 $gray-text,
114 $query: $query
115 );
116 }
117
118 // Floating label private mixin
119 @include _floating-label($query: $query);
120
121 // structural
122 @include _padding-horizontal(
123 $left: select-theme.$anchor-padding-left,
124 $left-with-leading-icon:
125 select-theme.$anchor-padding-left-with-leading-icon,
126 $right: select-theme.$anchor-padding-right,
127 $query: $query
128 );
129 @include select-icon-theme.size(
130 select-icon-theme.$icon-size,
131 $query: $query
132 );
133 @include select-theme.dropdown-icon-size(
134 select-icon-theme.$icon-size,
135 $query: $query
136 );
137 @include _option-side-padding(16px, $query: $query);
138 @include _option-graphic-trailing-margin(12px, $query: $query);
139
140 @include feature-targeting.targets($feat-structure) {
141 display: inline-flex;
142 position: relative; // Menu is absolutely positioned relative to this.
143 }
144
145 &__dropdown-icon {
146 @include _dropdown-icon-base($query: $query);
147 @include _dropdown-icon-inactive($query: $query);
148
149 @include feature-targeting.targets($feat-structure) {
150 @include rtl.reflexive-property(
151 margin,
152 select-icon-theme.$icon-horizontal-margin,
153 select-icon-theme.$icon-horizontal-margin
154 );
155 display: inline-flex;
156 position: relative;
157 align-self: center;
158 align-items: center;
159 justify-content: center;
160 flex-shrink: 0;
161 pointer-events: none;
162 }
163
164 .mdc-select--activated & {
165 @include _dropdown-icon-active($query: $query);
166 }
167 }
168 }
169
170 .mdc-select__anchor {
171 @include floating-label-mixins.float-position(
172 select-theme.$label-position-y,
173 $query: $query
174 );
175
176 @include feature-targeting.targets($feat-structure) {
177 width: select-theme.$default-width;
178 min-width: 0;
179 flex: 1 1 auto;
180 position: relative;
181 box-sizing: border-box;
182 overflow: hidden;
183 outline: none;
184 cursor: pointer;
185 }
186 }
187
188 @include _text($query: $query);
189
190 .mdc-select--invalid {
191 @include select-theme.label-color(
192 (
193 default: select-theme.$error-color,
194 focus: select-theme.$error-color,
195 ),
196 $query: $query
197 );
198 @include select-helper-text-theme.helper-text-validation-color(
199 select-theme.$error-color,
200 $query: $query
201 );
202 @include select-theme.dropdown-icon-color(
203 (
204 default: select-theme.$error-color,
205 focus: select-theme.$error-color,
206 ),
207 $query: $query
208 );
209 }
210
211 .mdc-select--disabled {
212 @include _disabled($query: $query);
213 }
214
215 .mdc-select--with-leading-icon {
216 @include _option-side-padding(12px, $query: $query);
217 }
218
219 @include _list($query: $query);
220
221 @include select-filled.core-styles($query: $query);
222 @include select-outlined.core-styles($query: $query);
223 @include select-ripple.core-styles($query: $query);
224 @include select-helper-text.helper-text-core-styles($query: $query);
225 @include select-icon.icon-core-styles($query: $query);
226}
227
228@mixin _list($query) {
229 $feat-structure: feature-targeting.create-target($query, structure);
230
231 @include dom-mixins.forced-colors-mode() {
232 .mdc-select__menu::before {
233 @include dom-mixins.transparent-border($query: $query);
234 }
235 }
236
237 .mdc-select__menu .mdc-deprecated-list,
238 .mdc-select__menu .mdc-list {
239 @include select-icon-theme.icon-horizontal-margins(0, 0, $query: $query);
240 @include list-mixins.deprecated-item-selected-text-color(
241 on-surface,
242 $query: $query
243 );
244 }
245
246 .mdc-select__menu .mdc-list-item__start {
247 @include feature-targeting.targets($feat-structure) {
248 display: inline-flex;
249 align-items: center;
250 }
251 }
252
253 .mdc-select__option {
254 @include list-evolution-mixins.item-spacing(16px, $query: $query);
255 }
256
257 .mdc-select__one-line-option {
258 @include list-evolution-mixins.one-line-item-height(48px, $query: $query);
259 }
260
261 .mdc-select__two-line-option {
262 @include list-evolution-mixins.two-line-item-height(64px, $query: $query);
263
264 &.mdc-list-item--with-two-lines {
265 .mdc-list-item__start {
266 @include feature-targeting.targets($feat-structure) {
267 margin-top: 20px;
268 }
269 }
270
271 .mdc-list-item__primary-text {
272 @include typography-mixins.text-baseline(
273 $top: 28px,
274 $bottom: 20px,
275 $query: $query
276 );
277 }
278
279 &.mdc-list-item--with-trailing-meta .mdc-list-item__end {
280 @include typography-mixins.text-baseline($top: 36px, $query: $query);
281 }
282 }
283 }
284
285 .mdc-select__option-with-leading-content {
286 @include list-evolution-mixins.item-start-spacing(12px, 0, $query: $query);
287 @include list-evolution-mixins.item-start-size(36px, 24px, $query: $query);
288 @include list-evolution-mixins.item-spacing(0, 12px, $query: $query);
289 }
290
291 .mdc-select__option-with-meta {
292 @include list-evolution-mixins.item-end-spacing(12px, $query: $query);
293 }
294}
295
296///
297/// Sets base dropdown icon styles.
298/// @access private
299///
300@mixin _dropdown-icon-base($query: feature-targeting.all()) {
301 $feat-structure: feature-targeting.create-target($query, structure);
302
303 .mdc-select__dropdown-icon-active,
304 .mdc-select__dropdown-icon-inactive {
305 @include feature-targeting.targets($feat-structure) {
306 position: absolute;
307 top: 0;
308 left: 0;
309 }
310 }
311
312 .mdc-select__dropdown-icon-graphic {
313 $svg-natural-width: 10px;
314 $svg-natural-height: 5px;
315
316 @include feature-targeting.targets($feat-structure) {
317 width: math.div($svg-natural-width, select-icon-theme.$icon-size) * 100%;
318 height: math.div($svg-natural-height, select-icon-theme.$icon-size) * 100%;
319 }
320 }
321}
322
323///
324/// Sets styles for transitioning the dropdown icon to inactive state.
325/// @access private
326///
327@mixin _dropdown-icon-inactive($query: feature-targeting.all()) {
328 $feat-structure: feature-targeting.create-target($query, structure);
329 $feat-animation: feature-targeting.create-target($query, animation);
330
331 .mdc-select__dropdown-icon-inactive {
332 @include feature-targeting.targets($feat-structure) {
333 opacity: 1;
334 }
335
336 @include feature-targeting.targets($feat-animation) {
337 transition: opacity select-theme.$icon-inactive-fade-in-duration linear
338 select-theme.$icon-inactive-fade-out-duration;
339 }
340 }
341
342 .mdc-select__dropdown-icon-active {
343 @include feature-targeting.targets($feat-structure) {
344 opacity: 0;
345 }
346
347 @include feature-targeting.targets($feat-animation) {
348 transition: opacity select-theme.$icon-inactive-fade-out-duration linear;
349 }
350 }
351}
352
353///
354/// Sets styles for transitioning the dropdown icon to activated state.
355/// @access private
356///
357@mixin _dropdown-icon-active($query: feature-targeting.all()) {
358 $feat-structure: feature-targeting.create-target($query, structure);
359 $feat-animation: feature-targeting.create-target($query, animation);
360
361 .mdc-select__dropdown-icon-inactive {
362 @include feature-targeting.targets($feat-structure) {
363 opacity: 0;
364 }
365
366 @include feature-targeting.targets($feat-animation) {
367 transition: opacity select-theme.$icon-active-fade-out-duration linear;
368 }
369 }
370
371 .mdc-select__dropdown-icon-active {
372 @include feature-targeting.targets($feat-structure) {
373 opacity: 1;
374 }
375
376 @include feature-targeting.targets($feat-animation) {
377 transition: opacity select-theme.$icon-active-fade-in-duration linear
378 select-theme.$icon-active-fade-out-duration;
379 }
380 }
381}
382
383///
384/// Sets the side padding for option text.
385/// @access private
386///
387@mixin _option-side-padding($side-padding, $query: feature-targeting.all()) {
388 $feat-structure: feature-targeting.create-target($query, structure);
389
390 .mdc-select__menu .mdc-deprecated-list-item {
391 @include feature-targeting.targets($feat-structure) {
392 @include rtl.reflexive-property(padding, $side-padding, $side-padding);
393 }
394 }
395}
396
397///
398/// Sets the traliing margin for an option's leading graphic.
399/// @access private
400///
401@mixin _option-graphic-trailing-margin(
402 $margin-right,
403 $query: feature-targeting.all()
404) {
405 $feat-structure: feature-targeting.create-target($query, structure);
406
407 .mdc-select__menu .mdc-deprecated-list-item__graphic {
408 @include feature-targeting.targets($feat-structure) {
409 @include rtl.reflexive-box(margin, right, $margin-right);
410 }
411 }
412}
413
414@mixin _floating-label($query: feature-targeting.all()) {
415 $feat-structure: feature-targeting.create-target($query, structure);
416
417 .mdc-floating-label {
418 @include feature-targeting.targets($feat-structure) {
419 top: 50%;
420 transform: translateY(-50%);
421 pointer-events: none;
422 }
423 }
424}
425
426@mixin _text($query: feature-targeting.all()) {
427 $feat-structure: feature-targeting.create-target($query, structure);
428 $feat-color: feature-targeting.create-target($query, color);
429
430 .mdc-select__selected-text-container {
431 @include feature-targeting.targets($feat-structure) {
432 display: flex;
433 appearance: none;
434 pointer-events: none;
435 box-sizing: border-box;
436 width: auto;
437 min-width: 0;
438 flex-grow: 1;
439 height: select-theme.$selected-text-height;
440 border: none;
441 outline: none;
442 padding: 0;
443 }
444
445 @include feature-targeting.targets($feat-color) {
446 background-color: transparent;
447 color: inherit; // Override default user agent stylesheet
448 }
449 }
450
451 .mdc-select__selected-text {
452 @include typography-mixins.typography(subtitle1, $query: $query);
453 @include typography-mixins.overflow-ellipsis($query: $query);
454
455 @include feature-targeting.targets($feat-structure) {
456 display: block;
457 width: 100%;
458 @include rtl.ignore-next-line();
459 text-align: left;
460 @include rtl.rtl {
461 @include rtl.ignore-next-line();
462 text-align: right;
463 }
464 }
465 }
466}
467
468@mixin _disabled($query: feature-targeting.all()) {
469 $feat-structure: feature-targeting.create-target($query, structure);
470
471 @include feature-targeting.targets($feat-structure) {
472 cursor: default;
473 pointer-events: none;
474 }
475}
476
477/// Adds horizontal padding to the selected text
478///
479/// @param {Number} $left - left side padding
480/// @param {Number} $left-with-leading-icon - left-side padding when a leading
481/// icon is present
482/// @param {Number} $right - right-side padding; note that a trailing icon is
483/// always present.
484@mixin _padding-horizontal(
485 $left,
486 $left-with-leading-icon,
487 $right,
488 $query: feature-targeting.all()
489) {
490 $feat-structure: feature-targeting.create-target($query, structure);
491
492 .mdc-select__anchor {
493 @include feature-targeting.targets($feat-structure) {
494 @include rtl.reflexive-property(padding, $left, $right);
495 }
496 }
497
498 &.mdc-select--with-leading-icon .mdc-select__anchor {
499 @include feature-targeting.targets($feat-structure) {
500 @include rtl.reflexive-property(padding, $left-with-leading-icon, $right);
501 }
502 }
503}