UNPKG

12.1 kBSCSSView Raw
1@import 'default-theme';
2@import 'theme-functions';
3@import 'variables';
4@import 'mixins';
5
6/** The width/height of the checkbox element. */
7$md-checkbox-size: $md-toggle-size !default;
8/** The width of the line used to draw the checkmark / mixedmark. */
9$md-checkbox-mark-stroke-size: 2/15 * $md-checkbox-size !default;
10/** The width of the checkbox border shown when the checkbox is unchecked. */
11$md-checkbox-border-width: 2px;
12/** The color of the checkbox border. */
13$md-checkbox-border-color: if($md-is-dark-theme, rgba(white, 0.7), rgba(black, 0.54)) !default;
14/** The color of the checkbox's checkmark / mixedmark. */
15$md-checkbox-mark-color: md-color($md-background, background);
16/** The color that is used as the checkbox background when it is checked. */
17$md-checkbox-background-color: md-color($md-accent, 500);
18/** The base duration used for the majority of transitions for the checkbox. */
19$md-checkbox-transition-duration: 90ms;
20/** The amount of spacing between the checkbox and its label. */
21$md-checkbox-item-spacing: $md-toggle-padding;
22
23// Manual calculation done on SVG
24$_md-checkbox-mark-path-length: 22.910259;
25$_md-checkbox-indeterminate-checked-easing-function: cubic-bezier(0.14, 0, 0, 1);
26
27/**
28 * Fades in the background of the checkbox when it goes from unchecked -> {checked,indeterminate}.
29 */
30@keyframes md-checkbox-fade-in-background {
31 0% {
32 opacity: 0;
33 }
34
35 50% {
36 opacity: 1;
37 }
38}
39
40/**
41 * Fades out the background of the checkbox when it goes from {checked,indeterminate} -> unchecked.
42 */
43@keyframes md-checkbox-fade-out-background {
44 0%, 50% {
45 opacity: 1;
46 }
47
48 100% {
49 opacity: 0;
50 }
51}
52
53/**
54 * "Draws" in the checkmark when the checkbox goes from unchecked -> checked.
55 */
56@keyframes md-checkbox-unchecked-checked-checkmark-path {
57 0%, 50% {
58 stroke-dashoffset: $_md-checkbox-mark-path-length;
59 }
60
61 50% {
62 animation-timing-function: $md-linear-out-slow-in-timing-function;
63 }
64
65 100% {
66 stroke-dashoffset: 0;
67 }
68}
69
70/**
71 * Horizontally expands the mixedmark when the checkbox goes from unchecked -> indeterminate.
72 */
73@keyframes md-checkbox-unchecked-indeterminate-mixedmark {
74 0%, 68.2% {
75 transform: scaleX(0);
76 }
77
78 68.2% {
79 animation-timing-function: cubic-bezier(0, 0, 0, 1);
80 }
81
82 100% {
83 transform: scaleX(1);
84 }
85}
86
87/**
88 * "Erases" the checkmark when the checkbox goes from checked -> unchecked.
89 */
90@keyframes md-checkbox-checked-unchecked-checkmark-path {
91 from {
92 animation-timing-function: $md-fast-out-linear-in-timing-function;
93 stroke-dashoffset: 0;
94 }
95
96 to {
97 stroke-dashoffset: $_md-checkbox-mark-path-length * -1;
98 }
99}
100
101/**
102 * Rotates and fades out the checkmark when the checkbox goes from checked -> indeterminate. This
103 * animation helps provide the illusion of the checkmark "morphing" into the mixedmark.
104 */
105@keyframes md-checkbox-checked-indeterminate-checkmark {
106 from {
107 animation-timing-function: $md-linear-out-slow-in-timing-function;
108 opacity: 1;
109 transform: rotate(0deg);
110 }
111
112 to {
113 opacity: 0;
114 transform: rotate(45deg);
115 }
116}
117
118/**
119 * Rotates and fades the checkmark back into position when the checkbox goes from indeterminate ->
120 * checked. This animation helps provide the illusion that the mixedmark is "morphing" into the
121 * checkmark.
122 */
123@keyframes md-checkbox-indeterminate-checked-checkmark {
124 from {
125 animation-timing-function: $_md-checkbox-indeterminate-checked-easing-function;
126 opacity: 0;
127 transform: rotate(45deg);
128 }
129
130 to {
131 opacity: 1;
132 transform: rotate(360deg);
133 }
134}
135
136/**
137 * Rotates and fades in the mixedmark when the checkbox goes from checked -> indeterminate. This
138 * animation, similar to md-checkbox-checked-indeterminate-checkmark, helps provide an illusion
139 * of "morphing" from checkmark -> mixedmark.
140 */
141@keyframes md-checkbox-checked-indeterminate-mixedmark {
142 from {
143 animation-timing-function: $md-linear-out-slow-in-timing-function;
144 opacity: 0;
145 transform: rotate(-45deg);
146 }
147
148 to {
149 opacity: 1;
150 transform: rotate(0deg);
151 }
152}
153
154/**
155 * Rotates and fades out the mixedmark when the checkbox goes from indeterminate -> checked. This
156 * animation, similar to md-checkbox-indeterminate-checked-checkmark, helps provide an illusion
157 * of "morphing" from mixedmark -> checkmark.
158 */
159@keyframes md-checkbox-indeterminate-checked-mixedmark {
160 from {
161 animation-timing-function: $_md-checkbox-indeterminate-checked-easing-function;
162 opacity: 1;
163 transform: rotate(0deg);
164 }
165
166 to {
167 opacity: 0;
168 transform: rotate(315deg);
169 }
170}
171
172/**
173 * Horizontally collapses and fades out the mixedmark when the checkbox goes from indeterminate ->
174 * unchecked.
175 */
176@keyframes md-checkbox-indeterminate-unchecked-mixedmark {
177 0% {
178 animation-timing-function: linear;
179 opacity: 1;
180 transform: scaleX(1);
181 }
182
183 32.8%, 100% {
184 opacity: 0;
185 transform: scaleX(0);
186 }
187}
188
189/**
190 * Applied to elements that cover the checkbox's entire inner container.
191 */
192%md-checkbox-cover-element {
193 bottom: 0;
194 left: 0;
195 position: absolute;
196 right: 0;
197 top: 0;
198}
199
200/**
201 * Applied to elements that are considered "marks" within the checkbox, e.g. the checkmark and
202 * the mixedmark.
203 */
204%md-checkbox-mark {
205 $width-padding-inset: 2 * $md-checkbox-border-width;
206 width: calc(100% - #{$width-padding-inset});
207}
208
209/**
210 * Applied to elements that appear to make up the outer box of the checkmark, such as the frame
211 * that contains the border and the actual background element that contains the marks.
212 */
213%md-checkbox-outer-box {
214 @extend %md-checkbox-cover-element;
215 border-radius: 2px;
216 box-sizing: border-box;
217 pointer-events: none;
218}
219
220md-checkbox {
221 cursor: pointer;
222}
223
224.md-checkbox-layout {
225 // `cursor: inherit` ensures that the wrapper element gets the same cursor as the md-checkbox
226 // (e.g. pointer by default, regular when disabled), instead of the browser default.
227 cursor: inherit;
228 align-items: baseline;
229 display: inline-flex;
230}
231
232.md-checkbox-inner-container {
233 display: inline-block;
234 height: $md-checkbox-size;
235 line-height: 0;
236 margin: auto;
237 margin-right: $md-checkbox-item-spacing;
238 order: 0;
239 position: relative;
240 vertical-align: middle;
241 white-space: nowrap;
242 width: $md-checkbox-size;
243
244 [dir='rtl'] & {
245 margin: {
246 left: $md-checkbox-item-spacing;
247 right: auto;
248 }
249 }
250}
251
252// TODO(kara): Remove this style when fixing vertical baseline
253.md-checkbox-layout .md-checkbox-label {
254 line-height: 24px;
255}
256
257.md-checkbox-frame {
258 @extend %md-checkbox-outer-box;
259
260 background-color: transparent;
261 border: $md-checkbox-border-width solid $md-checkbox-border-color;
262 transition: border-color $md-checkbox-transition-duration $md-linear-out-slow-in-timing-function;
263 will-change: border-color;
264}
265
266.md-checkbox-background {
267 @extend %md-checkbox-outer-box;
268
269 align-items: center;
270 display: inline-flex;
271 justify-content: center;
272 transition: background-color $md-checkbox-transition-duration
273 $md-linear-out-slow-in-timing-function,
274 opacity $md-checkbox-transition-duration $md-linear-out-slow-in-timing-function;
275 will-change: background-color, opacity;
276}
277
278.md-checkbox-checkmark {
279 @extend %md-checkbox-cover-element;
280 @extend %md-checkbox-mark;
281
282 fill: $md-checkbox-mark-color;
283 width: 100%;
284}
285
286.md-checkbox-checkmark-path {
287 // !important is needed here because a stroke must be set as an attribute on the SVG in order
288 // for line animation to work properly.
289 stroke: $md-checkbox-mark-color !important;
290 stroke: {
291 dashoffset: $_md-checkbox-mark-path-length;
292 dasharray: $_md-checkbox-mark-path-length;
293 width: $md-checkbox-mark-stroke-size;
294 }
295}
296
297.md-checkbox-mixedmark {
298 @extend %md-checkbox-mark;
299
300 background-color: $md-checkbox-mark-color;
301 height: floor($md-checkbox-mark-stroke-size);
302 opacity: 0;
303 transform: scaleX(0) rotate(0deg);
304}
305
306.md-checkbox-align-end {
307 .md-checkbox-inner-container {
308 order: 1;
309 margin: {
310 left: $md-checkbox-item-spacing;
311 right: auto;
312 }
313
314 [dir='rtl'] & {
315 margin: {
316 left: auto;
317 right: $md-checkbox-item-spacing;
318 }
319 }
320 }
321}
322
323.md-checkbox-checked {
324 .md-checkbox-checkmark {
325 opacity: 1;
326 }
327
328 .md-checkbox-checkmark-path {
329 stroke-dashoffset: 0;
330 }
331
332 .md-checkbox-mixedmark {
333 transform: scaleX(1) rotate(-45deg);
334 }
335
336 .md-checkbox-background {
337 background-color: $md-checkbox-background-color;
338 }
339}
340
341.md-checkbox-indeterminate {
342 .md-checkbox-background {
343 background-color: $md-checkbox-background-color;
344 }
345
346 .md-checkbox-checkmark {
347 opacity: 0;
348 transform: rotate(45deg);
349 }
350
351 .md-checkbox-checkmark-path {
352 stroke-dashoffset: 0;
353 }
354
355 .md-checkbox-mixedmark {
356 opacity: 1;
357 transform: scaleX(1) rotate(0deg);
358 }
359}
360
361
362.md-checkbox-unchecked {
363 .md-checkbox-background {
364 background-color: transparent;
365 }
366}
367
368.md-checkbox-disabled {
369 // NOTE(traviskaufman): While the spec calls for translucent blacks/whites for disabled colors,
370 // this does not work well with elements layered on top of one another. To get around this we
371 // blend the colors together based on the base color and the theme background.
372 $white-30pct-opacity-on-dark-theme: #686868;
373 $black-26pct-opacity-on-light-theme: #b0b0b0;
374 $disabled-color: if(
375 $md-is-dark-theme, $white-30pct-opacity-on-dark-theme, $black-26pct-opacity-on-light-theme);
376
377 cursor: default;
378
379 &.md-checkbox-checked,
380 &.md-checkbox-indeterminate {
381 .md-checkbox-background {
382 background-color: $disabled-color;
383 }
384 }
385
386 &:not(.md-checkbox-checked) {
387 .md-checkbox-frame {
388 border-color: $disabled-color;
389 }
390 }
391}
392
393.md-checkbox-anim {
394 $indeterminate-change-duration: 500ms;
395
396 &-unchecked-checked {
397 .md-checkbox-background {
398 animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-in-background;
399 }
400
401 .md-checkbox-checkmark-path {
402 // Instead of delaying the animation, we simply multiply its length by 2 and begin the
403 // animation at 50% in order to prevent a flash of styles applied to a checked checkmark
404 // as the background is fading in before the animation begins.
405 animation:
406 $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-unchecked-checked-checkmark-path;
407 }
408 }
409
410 &-unchecked-indeterminate {
411 .md-checkbox-background {
412 animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-in-background;
413 }
414
415 .md-checkbox-mixedmark {
416 animation:
417 $md-checkbox-transition-duration linear 0ms md-checkbox-unchecked-indeterminate-mixedmark;
418 }
419 }
420
421 &-checked-unchecked {
422 .md-checkbox-background {
423 animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-out-background;
424 }
425
426 .md-checkbox-checkmark-path {
427 animation:
428 $md-checkbox-transition-duration linear 0ms md-checkbox-checked-unchecked-checkmark-path;
429 }
430 }
431
432 &-checked-indeterminate {
433 .md-checkbox-checkmark {
434 animation:
435 $md-checkbox-transition-duration linear 0ms md-checkbox-checked-indeterminate-checkmark;
436 }
437
438 .md-checkbox-mixedmark {
439 animation:
440 $md-checkbox-transition-duration linear 0ms md-checkbox-checked-indeterminate-mixedmark;
441 }
442 }
443
444 &-indeterminate-checked {
445 .md-checkbox-checkmark {
446 animation:
447 $indeterminate-change-duration linear 0ms md-checkbox-indeterminate-checked-checkmark;
448 }
449
450 .md-checkbox-mixedmark {
451 animation:
452 $indeterminate-change-duration linear 0ms md-checkbox-indeterminate-checked-mixedmark;
453 }
454 }
455
456 &-indeterminate-unchecked {
457 .md-checkbox-background {
458 animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-out-background;
459 }
460
461 .md-checkbox-mixedmark {
462 animation:
463 $indeterminate-change-duration * 0.6 linear 0ms
464 md-checkbox-indeterminate-unchecked-mixedmark;
465 }
466 }
467}
468
469// Underlying native input element.
470// Visually hidden but still able to respond to focus.
471.md-checkbox-input {
472 @include md-visually-hidden;
473}
474
475@include md-temporary-ink-ripple(checkbox);