// // 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. // @import "@material/animation/functions"; @import "@material/density/functions"; @import "@material/feature-targeting/functions"; @import "@material/feature-targeting/mixins"; @import "@material/ripple/mixins"; @import "@material/ripple/variables"; @import "@material/theme/mixins"; @import "@material/theme/variables"; @import "@material/touch-target/mixins"; @import "@material/touch-target/variables"; @import "./functions"; @import "./variables"; $mdc-radio-ripple-target: ".mdc-radio__ripple"; @mixin mdc-radio-core-styles($query: mdc-feature-all()) { @include mdc-radio-without-ripple($query); @include mdc-radio-ripple($query); } // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other // radio styles. It is recommended that most users use `mdc-radio-core-styles` instead. @mixin mdc-radio-without-ripple($query: mdc-feature-all()) { // postcss-bem-linter: define radio $feat-animation: mdc-feature-create-target($query, animation); $feat-color: mdc-feature-create-target($query, color); $feat-structure: mdc-feature-create-target($query, structure); @include mdc-touch-target-wrapper($query); .mdc-radio { @include mdc-radio-unchecked-stroke-color($mdc-radio-unchecked-color, $query: $query); @include mdc-radio-checked-stroke-color($mdc-radio-baseline-theme-color, $query: $query); @include mdc-radio-ink-color($mdc-radio-baseline-theme-color, $query: $query); @include mdc-radio-disabled-unchecked-stroke-color($mdc-radio-disabled-circle-color, $query: $query); @include mdc-radio-disabled-checked-stroke-color($mdc-radio-disabled-circle-color, $query: $query); @include mdc-radio-disabled-ink-color($mdc-radio-disabled-circle-color, $query: $query); @include mdc-radio-focus-indicator-color($mdc-radio-baseline-theme-color, $query: $query); @include mdc-radio-density($mdc-radio-density-scale, $query: $query); @include mdc-feature-targets($feat-structure) { display: inline-block; position: relative; flex: 0 0 auto; box-sizing: content-box; width: $mdc-radio-icon-size; height: $mdc-radio-icon-size; cursor: pointer; /* @alternate */ will-change: opacity, transform, border-color, color; } // Container for radio circles and ripple. &__background { @include mdc-feature-targets($feat-structure) { display: inline-block; position: relative; box-sizing: border-box; width: $mdc-radio-icon-size; height: $mdc-radio-icon-size; } &::before { @include mdc-feature-targets($feat-structure) { position: absolute; transform: scale(0, 0); border-radius: 50%; opacity: 0; pointer-events: none; content: ""; } @include mdc-feature-targets($feat-animation) { transition: mdc-radio-exit(opacity), mdc-radio-exit(transform); } } } &__outer-circle { @include mdc-feature-targets($feat-structure) { position: absolute; top: 0; left: 0; box-sizing: border-box; width: 100%; height: 100%; border-width: 2px; border-style: solid; border-radius: 50%; } @include mdc-feature-targets($feat-animation) { transition: mdc-radio-exit(border-color); } } &__inner-circle { @include mdc-feature-targets($feat-structure) { position: absolute; top: 0; left: 0; box-sizing: border-box; width: 100%; height: 100%; transform: scale(0, 0); border-width: 10px; border-style: solid; border-radius: 50%; } @include mdc-feature-targets($feat-animation) { transition: mdc-radio-exit(transform), mdc-radio-exit(border-color); } } &__native-control { @include mdc-feature-targets($feat-structure) { position: absolute; margin: 0; padding: 0; opacity: 0; cursor: inherit; z-index: 1; } } &--touch { @include mdc-touch-target-component( $component-height: $mdc-radio-ripple-size, $component-width: $mdc-radio-ripple-size, $query: $query); @include mdc-radio-touch-target($size: $mdc-touch-target-height, $query: $query); } } .mdc-radio__native-control:checked, .mdc-radio__native-control:disabled { + .mdc-radio__background { @include mdc-feature-targets($feat-animation) { transition: mdc-radio-enter(opacity), mdc-radio-enter(transform); } .mdc-radio__outer-circle { @include mdc-feature-targets($feat-animation) { transition: mdc-radio-enter(border-color); } } .mdc-radio__inner-circle { @include mdc-feature-targets($feat-animation) { transition: mdc-radio-enter(transform), mdc-radio-enter(border-color); } } } } .mdc-radio--disabled { @include mdc-feature-targets($feat-structure) { cursor: default; pointer-events: none; } } .mdc-radio__native-control:checked { + .mdc-radio__background { .mdc-radio__inner-circle { @include mdc-feature-targets($feat-structure) { transform: scale(.5); } @include mdc-feature-targets($feat-animation) { transition: mdc-radio-enter(transform), mdc-radio-enter(border-color); } } } } .mdc-radio__native-control:disabled, [aria-disabled="true"] .mdc-radio__native-control { + .mdc-radio__background { @include mdc-feature-targets($feat-structure) { cursor: default; } } } .mdc-radio__native-control:focus { + .mdc-radio__background::before { @include mdc-feature-targets($feat-structure) { transform: scale(1); opacity: map-get($mdc-ripple-dark-ink-opacities, focus); } @include mdc-feature-targets($feat-animation) { transition: mdc-radio-enter(opacity), mdc-radio-enter(transform); } } } // postcss-bem-linter: end } // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other // radio styles. It is recommended that most users use `mdc-radio-core-styles` instead. @mixin mdc-radio-ripple($query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-ripple-common($query); .mdc-radio { @include mdc-ripple-surface($query: $query, $ripple-target: $mdc-radio-ripple-target); @include mdc-ripple-radius-unbounded($query: $query, $ripple-target: $mdc-radio-ripple-target); @include mdc-states( $color: $mdc-radio-baseline-theme-color, $query: $query, $ripple-target: $mdc-radio-ripple-target); &.mdc-ripple-upgraded--background-focused { .mdc-radio__background::before { @include mdc-feature-targets($feat-structure) { content: none; } } } } #{$mdc-radio-ripple-target} { @include mdc-ripple-target-common($query: $query); } } /// /// Sets the stroke color of an unchecked, enabled radio button. /// @param {Color} $color - The desired stroke color. /// @mixin mdc-radio-unchecked-stroke-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-enabled-unchecked_ { @include mdc-radio-stroke-color_($color, $query: $query); } } /// /// Sets the stroke color of a checked, enabled radio button. /// @param {Color} $color - The desired stroke color. /// @mixin mdc-radio-checked-stroke-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-enabled-checked_ { @include mdc-radio-stroke-color_($color, $query:$query); } } /// /// Sets the ink color of an enabled radio button. /// @param {Color} $color - The desired ink color. /// @mixin mdc-radio-ink-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-enabled_ { @include mdc-radio-ink-color_($color, $query: $query); } } /// /// Sets the stroke color of an unchecked, disabled radio button. /// @param {Color} $color - The desired stroke color. /// @mixin mdc-radio-disabled-unchecked-stroke-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-disabled-unchecked_ { @include mdc-radio-stroke-color_($color, $query: $query); } } /// /// Sets the stroke color of a checked, disabled radio button. /// @param {Color} $color - The desired stroke color. /// @mixin mdc-radio-disabled-checked-stroke-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-disabled-checked_ { @include mdc-radio-stroke-color_($color, $query: $query); } } /// /// Sets the ink color of a disabled radio button. /// @param {Color} $color - The desired ink color /// @mixin mdc-radio-disabled-ink-color($color, $query: mdc-feature-all()) { @include mdc-radio-if-disabled_ { @include mdc-radio-ink-color_($color, $query: $query); } } @mixin mdc-radio-focus-indicator-color($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); .mdc-radio__background::before { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(background-color, $color, $edgeOptOut: true); } } } /// /// Sets radio touch target size which can be more than the ripple size. Param `$ripple-size` is required for custom /// ripple size. /// /// @param {Number} $size Size of touch target (Native input) in `px`. /// @param {Number} $ripple-size Size of ripple in `px`. Required only for custom ripple size. /// @mixin mdc-radio-touch-target( $size: $mdc-radio-ripple-size, $ripple-size: $mdc-radio-ripple-size, $query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); $offset: ($ripple-size - $size) / 2; .mdc-radio__native-control { @include mdc-feature-targets($feat-structure) { top: $offset; right: $offset; left: $offset; width: $size; height: $size; } } } /// /// Sets density scale for radio. /// /// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values /// `-3`, `-2`, `-1`, `0`. /// @mixin mdc-radio-density($density-scale, $query: mdc-feature-all()) { $size: mdc-density-prop-value( $density-config: $mdc-radio-density-config, $density-scale: $density-scale, $property-name: size, ); @include mdc-radio-ripple-size($size, $query: $query); // Sets touch target size same as ripple size. @include mdc-radio-touch-target($size: $size, $ripple-size: $size, $query: $query); @if $density-scale != 0 { @include mdc-radio-touch-target-reset_($query: $query); } } /// /// Sets radio ripple size. /// /// @param {Number} $size - Ripple size in `px`. /// @mixin mdc-radio-ripple-size($size, $query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); $padding: ($size - $mdc-radio-icon-size) / 2; @include mdc-feature-targets($feat-structure) { padding: $padding; } .mdc-radio__background::before { @include mdc-feature-targets($feat-structure) { top: -$padding; left: -$padding; width: $size; height: $size; } } } /// /// Resets touch target-related styles. This is called from the density mixin to /// automatically remove the increased touch target, since dense components /// don't have the same default a11y requirements. /// @access private /// @mixin mdc-radio-touch-target-reset_($query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-feature-targets($feat-structure) { margin: 0; } } /// /// Helps select the radio background only when its native control is in the /// enabled state. /// @access private /// @mixin mdc-radio-if-enabled_ { .mdc-radio__native-control:enabled + { @content; } } /// /// Helps select the radio background only when its native control is in the /// enabled & unchecked state. /// @access private /// @mixin mdc-radio-if-enabled-unchecked_ { .mdc-radio__native-control:enabled:not(:checked) + { @content; } } /// /// Helps select the radio background only when its native control is in the /// enabled & checked state. /// @access private /// @mixin mdc-radio-if-enabled-checked_ { .mdc-radio__native-control:enabled:checked + { @content; } } /// /// Helps select the radio background only when its native control is in the /// disabled state. /// @access private /// @mixin mdc-radio-if-disabled_ { [aria-disabled="true"] .mdc-radio__native-control, .mdc-radio__native-control:disabled { + { @content; } } } /// /// Helps select the radio background only when its native control is in the /// disabled & unchecked state. /// @access private /// @mixin mdc-radio-if-disabled-unchecked_ { [aria-disabled="true"] .mdc-radio__native-control, .mdc-radio__native-control:disabled { &:not(:checked) + { @content; } } } /// /// Helps select the radio background only when its native control is in the /// disabled & checked state. /// @access private /// @mixin mdc-radio-if-disabled-checked_ { [aria-disabled="true"] .mdc-radio__native-control, .mdc-radio__native-control:disabled { &:checked + { @content; } } } /// /// Sets the ink color for radio. This is wrapped in a mixin /// that qualifies state such as `mdc-radio-if-enabled_` /// @access private /// @mixin mdc-radio-ink-color_($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); .mdc-radio__background .mdc-radio__inner-circle { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(border-color, $color); } } } /// /// Sets the stroke color for radio. This is wrapped in a mixin /// that qualifies state such as `mdc-radio-if-enabled_` /// @access private /// @mixin mdc-radio-stroke-color_($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); .mdc-radio__background .mdc-radio__outer-circle { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(border-color, $color); } } }