| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- //
- // Copyright 2016 Google Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- // stylelint-disable selector-class-pattern --
- // Selector '.mdc-*' should only be used in this project.
- @use 'sass:map';
- @use 'sass:math';
- @use '@material/animation/functions' as functions2;
- @use '@material/animation/variables' as animation-variables;
- @use '@material/density/functions' as density-functions;
- @use '@material/dom/dom';
- @use '@material/feature-targeting/feature-targeting';
- @use '@material/focus-ring/focus-ring';
- @use '@material/rtl/rtl';
- @use '@material/ripple/ripple';
- @use '@material/ripple/ripple-theme';
- @use '@material/touch-target/mixins' as touch-target-mixins;
- @use '@material/theme/theme-color';
- @use './checkbox-custom-properties';
- @use '@material/theme/theme';
- @use '@material/theme/color-custom-properties';
- @use '@material/theme/custom-properties';
- @use '@material/touch-target/variables' as touch-target-variables;
- @use './checkbox-theme';
- ///
- /// Checkbox and ripple styles.
- ///
- @mixin core-styles($query: feature-targeting.all()) {
- @include without-ripple($query);
- @include ripple-styles($query);
- }
- /// Checkbox styles (Excluding ripple styles).
- ///
- /// NOTE: This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
- /// checkbox styles. It is recommended that most users use `mdc-checkbox-core-styles` instead.
- // TODO(b/162887560): Rename to `checkbox-without-ripple-styles()`
- @mixin without-ripple($query: feature-targeting.all()) {
- // TODO(b/165005345): Include theme-styles() after static-styles().
- @include theme-styles($query: $query);
- @include static-styles($query: $query);
- }
- /// Checkbox static styles.
- /// Checkbox styles that are not customizable should go here.
- @mixin static-styles($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include touch-target-mixins.wrapper($query); // COPYBARA_COMMENT_THIS_LINE
- @include feature-targeting.targets($feat-animation) {
- @include mark-keyframes_;
- }
- .mdc-checkbox {
- @include feature-targeting.targets($feat-structure) {
- @include base_;
- }
- @include ripple-theme.focus {
- .mdc-checkbox__focus-ring {
- @include focus-ring.focus-ring(
- $query: $query,
- $container-outer-padding-vertical: 0,
- $container-outer-padding-horizontal: 0
- );
- }
- }
- // Turn off focus ring for IE when HCM is turn off. For some reason this
- // adds space to the bottom on the focused checkbox inside a dialog.
- @media all and (-ms-high-contrast: none) {
- .mdc-checkbox__focus-ring {
- display: none;
- }
- }
- }
- @include dom.forced-colors-mode {
- .mdc-checkbox__mixedmark {
- @include feature-targeting.targets($feat-structure) {
- margin: 0 1px; // Extra horizontal space around mixedmark symbol.
- }
- }
- }
- // Needed to disable hover effects on CSS-only (non-JS) checkboxes
- .mdc-checkbox--disabled {
- @include feature-targeting.targets($feat-structure) {
- @include disabled_;
- }
- }
- .mdc-checkbox__background {
- @include background_($query);
- }
- .mdc-checkbox__checkmark {
- @include checkmark_($query);
- }
- .mdc-checkbox__checkmark-path {
- @include checkmark-path_($query);
- }
- .mdc-checkbox__mixedmark {
- @include mixedmark_($query);
- }
- .mdc-checkbox--anim {
- @include feature-targeting.targets($feat-animation) {
- @include anim_;
- }
- }
- .mdc-checkbox__native-control:checked ~ .mdc-checkbox__background,
- .mdc-checkbox__native-control:indeterminate ~ .mdc-checkbox__background,
- .mdc-checkbox__native-control[data-indeterminate='true']
- ~ .mdc-checkbox__background {
- @include feature-targeting.targets($feat-animation) {
- @include background--marked_;
- }
- .mdc-checkbox__checkmark-path {
- @include feature-targeting.targets($feat-structure) {
- @include checkmark-path--marked_;
- }
- }
- }
- .mdc-checkbox__native-control {
- @include feature-targeting.targets($feat-structure) {
- @include native-control_;
- }
- &:disabled {
- @include feature-targeting.targets($feat-structure) {
- @include disabled_;
- }
- }
- }
- .mdc-checkbox--touch {
- @include checkbox-theme.touch-target(
- custom-properties.create(
- checkbox-state-layer-size,
- touch-target-variables.$height
- ),
- custom-properties.create(
- checkbox-state-layer-size,
- checkbox-theme.$ripple-size
- ),
- $query: $query
- );
- }
- .mdc-checkbox__native-control:checked ~ .mdc-checkbox__background {
- .mdc-checkbox__checkmark {
- @include checkmark--checked_($query);
- }
- .mdc-checkbox__mixedmark {
- @include feature-targeting.targets($feat-structure) {
- @include mixedmark--checked_;
- }
- }
- }
- .mdc-checkbox__native-control:indeterminate ~ .mdc-checkbox__background,
- .mdc-checkbox__native-control[data-indeterminate='true']
- ~ .mdc-checkbox__background {
- .mdc-checkbox__checkmark {
- @include checkmark--indeterminate_($query);
- }
- .mdc-checkbox__mixedmark {
- @include feature-targeting.targets($feat-structure) {
- @include mixedmark--indeterminate_;
- }
- }
- }
- // JS checkbox
- .mdc-checkbox.mdc-checkbox--upgraded {
- .mdc-checkbox__background,
- .mdc-checkbox__checkmark,
- .mdc-checkbox__checkmark-path,
- .mdc-checkbox__mixedmark {
- @include feature-targeting.targets($feat-animation) {
- @include child--upgraded_;
- }
- }
- }
- }
- /// Checkbox theme styles.
- /// Checkbox styles that are customizable should go here.
- @mixin theme-styles($query: feature-targeting.all()) {
- .mdc-checkbox {
- @include checkbox-theme.theme-deprecated(
- checkbox-theme.$light-theme-deprecated,
- $query: $query
- );
- }
- }
- /// Checkbox's ripple styles.
- ///
- /// NOTE: This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
- /// checkbox styles. It is recommended that most users use `mdc-checkbox-core-styles` instead.
- @mixin ripple-styles($query: feature-targeting.all()) {
- $feat-structure: feature-targeting.create-target($query, structure);
- @include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE
- .mdc-checkbox {
- @include ripple.surface(
- $query: $query,
- $ripple-target: checkbox-theme.$ripple-target
- );
- @include ripple.radius-unbounded(
- $query: $query,
- $ripple-target: checkbox-theme.$ripple-target
- );
- @include ripple-theme.behind-content(
- checkbox-theme.$ripple-target,
- $query: $query
- );
- }
- #{checkbox-theme.$ripple-target} {
- @include ripple.target-common($query: $query);
- }
- }
- @mixin base_ {
- display: inline-block;
- &[hidden] {
- display: none;
- }
- position: relative;
- flex: 0 0 checkbox-theme.$icon-size;
- box-sizing: content-box;
- width: checkbox-theme.$icon-size;
- height: checkbox-theme.$icon-size;
- line-height: 0;
- white-space: nowrap;
- cursor: pointer;
- vertical-align: bottom;
- }
- @mixin disabled_ {
- cursor: default;
- pointer-events: none;
- }
- @mixin child--upgraded_ {
- transition: none;
- }
- // Animation
- @mixin anim_ {
- $mdc-checkbox-indeterminate-change-duration_: 500ms;
- // stylelint-disable no-unknown-animations -- allow unknown animations
- &-unchecked-checked,
- &-unchecked-indeterminate,
- &-checked-unchecked,
- &-indeterminate-unchecked {
- .mdc-checkbox__background {
- animation-duration: checkbox-theme.$transition-duration * 2;
- animation-timing-function: linear;
- }
- }
- &-unchecked-checked {
- .mdc-checkbox__checkmark-path {
- // Instead of delaying the animation, we simply multiply its length by 2 and begin the
- // animation at 50% in order to prevent a flash of styles applied to a checked checkmark
- // as the background is fading in before the animation begins.
- animation: mdc-checkbox-unchecked-checked-checkmark-path
- checkbox-theme.$transition-duration * 2 linear 0s;
- transition: none;
- }
- }
- &-unchecked-indeterminate {
- .mdc-checkbox__mixedmark {
- animation: mdc-checkbox-unchecked-indeterminate-mixedmark
- checkbox-theme.$transition-duration linear 0s;
- transition: none;
- }
- }
- &-checked-unchecked {
- .mdc-checkbox__checkmark-path {
- animation: mdc-checkbox-checked-unchecked-checkmark-path
- checkbox-theme.$transition-duration linear 0s;
- transition: none;
- }
- }
- &-checked-indeterminate {
- .mdc-checkbox__checkmark {
- animation: mdc-checkbox-checked-indeterminate-checkmark
- checkbox-theme.$transition-duration linear 0s;
- transition: none;
- }
- .mdc-checkbox__mixedmark {
- animation: mdc-checkbox-checked-indeterminate-mixedmark
- checkbox-theme.$transition-duration linear 0s;
- transition: none;
- }
- }
- &-indeterminate-checked {
- .mdc-checkbox__checkmark {
- animation: mdc-checkbox-indeterminate-checked-checkmark
- $mdc-checkbox-indeterminate-change-duration_ linear 0s;
- transition: none;
- }
- .mdc-checkbox__mixedmark {
- animation: mdc-checkbox-indeterminate-checked-mixedmark
- $mdc-checkbox-indeterminate-change-duration_ linear 0s;
- transition: none;
- }
- }
- &-indeterminate-unchecked {
- .mdc-checkbox__mixedmark {
- animation: mdc-checkbox-indeterminate-unchecked-mixedmark
- $mdc-checkbox-indeterminate-change-duration_ * 0.6 linear 0s;
- transition: none;
- }
- }
- // stylelint-enable no-unknown-animations
- }
- @mixin background_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- $feat-color: feature-targeting.create-target($query, color);
- @include feature-targeting.targets($feat-structure) {
- display: inline-flex;
- position: absolute;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
- width: checkbox-theme.$icon-size;
- height: checkbox-theme.$icon-size;
- // border-color is overridden by the mdc-checkbox-unmarked-stroke-color() mixin
- border: checkbox-theme.$border-width solid currentColor;
- border-radius: 2px;
- background-color: transparent;
- pointer-events: none;
- will-change: background-color, border-color;
- }
- @include feature-targeting.targets($feat-animation) {
- transition: transition-exit(background-color), transition-exit(border-color);
- }
- }
- @mixin background--marked_ {
- transition: transition-enter(border-color), transition-enter(background-color);
- }
- // stylelint-disable block-no-empty -- For backward compatibility.
- @mixin focus-indicator_($query: feature-targeting.all()) {
- }
- @mixin focus-indicator--focused_($query: feature-targeting.all()) {
- }
- // stylelint-enable block-no-empty
- // Native input
- @mixin native-control_ {
- position: absolute;
- margin: 0;
- padding: 0;
- opacity: 0;
- cursor: inherit;
- }
- // Check mark
- @mixin checkmark_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-structure) {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- width: 100%;
- opacity: 0;
- }
- @include feature-targeting.targets($feat-animation) {
- transition: transition-exit(
- opacity,
- 0ms,
- checkbox-theme.$transition-duration * 2
- );
- }
- .mdc-checkbox--upgraded & {
- @include feature-targeting.targets($feat-structure) {
- opacity: 1;
- }
- }
- }
- @mixin checkmark--checked_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-animation) {
- transition: transition-enter(
- opacity,
- 0ms,
- checkbox-theme.$transition-duration * 2
- ),
- transition-enter(transform, 0ms, checkbox-theme.$transition-duration * 2);
- }
- @include feature-targeting.targets($feat-structure) {
- opacity: 1;
- }
- }
- @mixin checkmark--indeterminate_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-structure) {
- @include rtl.ignore-next-line();
- transform: rotate(45deg);
- opacity: 0;
- }
- @include feature-targeting.targets($feat-animation) {
- transition: transition-exit(
- opacity,
- 0ms,
- checkbox-theme.$transition-duration
- ),
- transition-exit(transform, 0ms, checkbox-theme.$transition-duration);
- }
- }
- // Check mark path
- @mixin checkmark-path_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-animation) {
- transition: transition-exit(
- stroke-dashoffset,
- 0ms,
- checkbox-theme.$transition-duration * 2
- );
- }
- @include feature-targeting.targets($feat-structure) {
- stroke: currentColor;
- stroke-width: checkbox-theme.$mark-stroke-size * 1.3;
- stroke-dashoffset: $mark-path-length_;
- stroke-dasharray: $mark-path-length_;
- }
- }
- @mixin checkmark-path--marked_ {
- stroke-dashoffset: 0;
- }
- // Mixed mark
- @mixin mixedmark_($query: feature-targeting.all()) {
- $feat-animation: feature-targeting.create-target($query, animation);
- $feat-structure: feature-targeting.create-target($query, structure);
- @include feature-targeting.targets($feat-structure) {
- width: 100%;
- height: 0;
- @include rtl.ignore-next-line();
- transform: scaleX(0) rotate(0deg);
- border-width: math.div(math.floor(checkbox-theme.$mark-stroke-size), 2);
- border-style: solid;
- opacity: 0;
- }
- @include feature-targeting.targets($feat-animation) {
- transition: transition-exit(opacity), transition-exit(transform);
- }
- }
- @mixin mixedmark--checked_ {
- @include rtl.ignore-next-line();
- transform: scaleX(1) rotate(-45deg);
- }
- @mixin mixedmark--indeterminate_ {
- @include rtl.ignore-next-line();
- transform: scaleX(1) rotate(0deg);
- opacity: 1;
- }
- @function transition-enter(
- $property,
- $delay: 0ms,
- $duration: checkbox-theme.$transition-duration
- ) {
- @return functions2.enter($property, $duration, $delay);
- }
- @function transition-exit(
- $property,
- $delay: 0ms,
- $duration: checkbox-theme.$transition-duration
- ) {
- @return functions2.exit-temporary($property, $duration, $delay);
- }
- // Manual calculation done on SVG
- $mark-path-length_: 29.7833385 !default;
- $indeterminate-checked-easing-function_: cubic-bezier(0.14, 0, 0, 1) !default;
- @mixin mark-keyframes_ {
- @keyframes mdc-checkbox-unchecked-checked-checkmark-path {
- 0%,
- 50% {
- stroke-dashoffset: $mark-path-length_;
- }
- 50% {
- animation-timing-function: animation-variables.$deceleration-curve-timing-function;
- }
- 100% {
- stroke-dashoffset: 0;
- }
- }
- @keyframes mdc-checkbox-unchecked-indeterminate-mixedmark {
- 0%,
- 68.2% {
- transform: scaleX(0);
- }
- 68.2% {
- animation-timing-function: cubic-bezier(0, 0, 0, 1);
- }
- 100% {
- transform: scaleX(1);
- }
- }
- @keyframes mdc-checkbox-checked-unchecked-checkmark-path {
- from {
- animation-timing-function: animation-variables.$acceleration-curve-timing-function;
- opacity: 1;
- stroke-dashoffset: 0;
- }
- to {
- opacity: 0;
- stroke-dashoffset: $mark-path-length_ * -1;
- }
- }
- @keyframes mdc-checkbox-checked-indeterminate-checkmark {
- from {
- animation-timing-function: animation-variables.$deceleration-curve-timing-function;
- @include rtl.ignore-next-line();
- transform: rotate(0deg);
- opacity: 1;
- }
- to {
- @include rtl.ignore-next-line();
- transform: rotate(45deg);
- opacity: 0;
- }
- }
- @keyframes mdc-checkbox-indeterminate-checked-checkmark {
- from {
- animation-timing-function: $indeterminate-checked-easing-function_;
- @include rtl.ignore-next-line();
- transform: rotate(45deg);
- opacity: 0;
- }
- to {
- @include rtl.ignore-next-line();
- transform: rotate(360deg);
- opacity: 1;
- }
- }
- @keyframes mdc-checkbox-checked-indeterminate-mixedmark {
- from {
- animation-timing-function: mdc-animation-deceleration-curve-timing-function;
- @include rtl.ignore-next-line();
- transform: rotate(-45deg);
- opacity: 0;
- }
- to {
- @include rtl.ignore-next-line();
- transform: rotate(0deg);
- opacity: 1;
- }
- }
- @keyframes mdc-checkbox-indeterminate-checked-mixedmark {
- from {
- animation-timing-function: $indeterminate-checked-easing-function_;
- @include rtl.ignore-next-line();
- transform: rotate(0deg);
- opacity: 1;
- }
- to {
- @include rtl.ignore-next-line();
- transform: rotate(315deg);
- opacity: 0;
- }
- }
- @keyframes mdc-checkbox-indeterminate-unchecked-mixedmark {
- 0% {
- animation-timing-function: linear;
- transform: scaleX(1);
- opacity: 1;
- }
- 32.8%,
- 100% {
- transform: scaleX(0);
- opacity: 0;
- }
- }
- }
|