// // 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/elevation/mixins"; @import "@material/feature-targeting/functions"; @import "@material/feature-targeting/mixins"; @import "@material/ripple/mixins"; @import "@material/rtl/mixins"; @import "@material/theme/functions"; @import "@material/theme/mixins"; @import "@material/touch-target/mixins"; @import "@material/typography/mixins"; @import "@material/shape/mixins"; @import "@material/shape/functions"; @import "@material/density/functions"; @import "./variables"; $mdc-button-ripple-target: ".mdc-button__ripple"; @mixin mdc-button-core-styles($query: mdc-feature-all()) { @include mdc-button-without-ripple($query); @include mdc-button-ripple($query); } @mixin mdc-button-theme-baseline($query: mdc-feature-all()) { .mdc-button { @include mdc-button-density($mdc-button-density-scale, $query: $query); } } // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other // button styles. It is recommended that most users use `mdc-button-core-styles` instead. @mixin mdc-button-without-ripple($query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); $feat-structure: mdc-feature-create-target($query, structure); @include mdc-touch-target-wrapper($query); // postcss-bem-linter: define button .mdc-button { @include mdc-button-base_($query); @include mdc-button-shape-radius(small, $query: $query); @include mdc-button-container-fill-color(transparent, $query); // The icon CSS class overrides styles defined in the .material-icons CSS // class, which is loaded separately so the order of CSS definitions is not // guaranteed. Therefore, increase specifity by nesting this class to ensure // overrides apply. .mdc-button__icon { @include mdc-feature-targets($feat-structure) { @include mdc-button__icon_; } } .mdc-button__touch { @include mdc-touch-target($query); } @include mdc-button-ink-color(primary, $query); } .mdc-button__label + .mdc-button__icon { @include mdc-feature-targets($feat-structure) { @include mdc-button__icon-trailing_; } } // stylelint-disable-next-line selector-no-qualifying-type svg.mdc-button__icon { @include mdc-feature-targets($feat-structure) { @include mdc-button__icon-svg_; } } .mdc-button--raised, .mdc-button--unelevated, .mdc-button--outlined { .mdc-button__icon { @include mdc-feature-targets($feat-structure) { // Icons inside contained buttons have different styles due to increased button padding @include mdc-button__icon-contained_; } } .mdc-button__label + .mdc-button__icon { @include mdc-feature-targets($feat-structure) { @include mdc-button__icon-contained-trailing_; } } } .mdc-button--raised, .mdc-button--unelevated { @include mdc-button--filled_($query); @include mdc-button-container-fill-color(primary, $query); @include mdc-button-ink-color(on-primary, $query); } .mdc-button--raised { @include mdc-button--raised_($query); } .mdc-button--outlined { @include mdc-button--outlined_($query); @include mdc-button-outline-width($mdc-button-outlined-border-width, $query: $query); @include mdc-button-outline-color(primary, $query); } .mdc-button--touch { @include mdc-touch-target-component( $component-height: $mdc-button-height, $query: $query); } // postcss-bem-linter: end } // This API is intended for use by frameworks that may want to separate the ripple-related styles from the other // button styles. It is recommended that most users use `mdc-button-core-styles` instead. @mixin mdc-button-ripple($query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-ripple-common($query); .mdc-button { @include mdc-ripple-surface($query: $query, $ripple-target: $mdc-button-ripple-target); @include mdc-ripple-radius-bounded( $query: $query, $ripple-target: $mdc-button-ripple-target); @include mdc-states( $color: primary, $query: $query, $ripple-target: $mdc-button-ripple-target); #{$mdc-button-ripple-target} { @include mdc-feature-targets($feat-structure) { position: absolute; // Ripple needs content-box as the box sizing and box-sizing: border-box // is often set as a default, so we override that here. box-sizing: content-box; width: 100%; height: 100%; overflow: hidden; } } // Ripple targets inside outlined buttons set their own `top`/`left`, // depending on the border width. &:not(.mdc-button--outlined) #{$mdc-button-ripple-target} { @include mdc-feature-targets($feat-structure) { top: 0; left: 0; } } } .mdc-button--raised, .mdc-button--unelevated { @include mdc-states( $color: on-primary, $query: $query, $ripple-target: $mdc-button-ripple-target); } } @mixin mdc-button-filled-accessible($container-fill-color, $query: mdc-feature-all()) { $fill-tone: mdc-theme-tone($container-fill-color); @include mdc-button-container-fill-color($container-fill-color, $query); @if ($fill-tone == "dark") { @include mdc-button-ink-color(text-primary-on-dark, $query); @include mdc-states( $color: text-primary-on-dark, $query: $query, $ripple-target: $mdc-button-ripple-target); } @else { @include mdc-button-ink-color(text-primary-on-light, $query); @include mdc-states( $color: text-primary-on-light, $query: $query, $ripple-target: $mdc-button-ripple-target); } } @mixin mdc-button-container-fill-color($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); // :not(:disabled) is used to support link styled as button // as link does not support :enabled style &:not(:disabled) { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(background-color, $color, $edgeOptOut: true); } } } @mixin mdc-button-outline-color($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); &:not(:disabled) { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(border-color, $color); } } } @mixin mdc-button-icon-color($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); &:not(:disabled) .mdc-button__icon { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(color, $color); } } } @mixin mdc-button-ink-color($color, $query: mdc-feature-all()) { $feat-color: mdc-feature-create-target($query, color); &:not(:disabled) { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(color, $color); } } } /// /// Sets density scale for button. /// /// @param {Number | String} $density-scale - Density scale value for component. Supported density scale values `-3`, /// `-2`, `-1`, `0`. /// @mixin mdc-button-density($density-scale, $query: mdc-feature-all()) { $height: mdc-density-prop-value( $density-config: $mdc-button-density-config, $density-scale: $density-scale, $property-name: height, ); @include mdc-button-height($height, $query: $query); @if $density-scale != 0 { @include mdc-button-touch-target-reset_($query: $query); } } /// /// 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-button-touch-target-reset_($query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-feature-targets($feat-structure) { margin-top: 0; margin-bottom: 0; } .mdc-button__touch { @include mdc-feature-targets($feat-structure) { display: none; } } } @mixin mdc-button-height($height, $query: $query) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-feature-targets($feat-structure) { height: $height; } } @mixin mdc-button-shape-radius($radius, $rtl-reflexive: false, $density-scale: $mdc-button-density-scale, $query: mdc-feature-all()) { $height: mdc-density-prop-value( $density-config: $mdc-button-density-config, $density-scale: $density-scale, $property-name: height, ); $resolved-radius: mdc-shape-resolve-percentage-radius($height, $radius); @include mdc-shape-radius($resolved-radius, $rtl-reflexive, $query: $query); #{$mdc-button-ripple-target} { @include mdc-shape-radius($resolved-radius, $rtl-reflexive, $query: $query); } } @mixin mdc-button-horizontal-padding($padding, $query: mdc-feature-all()) { $feat-structure: mdc-feature-create-target($query, structure); @include mdc-feature-targets($feat-structure) { // $padding should be a single value; enforce it by specifying all 4 sides in the output padding: 0 $padding 0 $padding; } } @mixin mdc-button-outline-width( $outline-width, $padding: $mdc-button-contained-horizontal-padding, $query: mdc-feature-all() ) { $feat-structure: mdc-feature-create-target($query, structure); // Note: Adjust padding to maintain consistent width with non-outlined buttons $padding-value: max($padding - $outline-width, 0); @include mdc-button-horizontal-padding($padding-value, $query); @include mdc-feature-targets($feat-structure) { border-width: $outline-width; } #{$mdc-button-ripple-target} { @include mdc-feature-targets($feat-structure) { top: -$outline-width; left: -$outline-width; border: $outline-width solid transparent; } } } @mixin mdc-button-base_($query) { $feat-color: mdc-feature-create-target($query, color); $feat-structure: mdc-feature-create-target($query, structure); @include mdc-typography(button, $query); @include mdc-button-horizontal-padding($mdc-button-horizontal-padding, $query); @include mdc-feature-targets($feat-structure) { display: inline-flex; position: relative; align-items: center; justify-content: center; box-sizing: border-box; min-width: 64px; border: none; outline: none; /* @alternate */ line-height: inherit; user-select: none; -webkit-appearance: none; // Even though `visible` is the default, IE 11 computes the property as // `hidden` in some cases, unless it's explicitly defined here. overflow: visible; vertical-align: middle; } &::-moz-focus-inner { @include mdc-feature-targets($feat-structure) { padding: 0; border: 0; } } // postcss-bem-linter: ignore &:active { @include mdc-feature-targets($feat-structure) { outline: none; } } &:hover { @include mdc-feature-targets($feat-structure) { cursor: pointer; } } &:disabled { @include mdc-feature-targets($feat-color) { @include mdc-theme-prop(background-color, transparent); color: $mdc-button-disabled-ink-color; } @include mdc-feature-targets($feat-structure) { cursor: default; pointer-events: none; } } } @mixin mdc-button__icon_ { @include mdc-rtl-reflexive-box(margin, right, 8px); display: inline-block; width: 18px; height: 18px; font-size: 18px; vertical-align: top; } @mixin mdc-button__icon-trailing_ { @include mdc-rtl-reflexive-box(margin, left, 8px); } @mixin mdc-button__icon-svg_ { fill: currentColor; } @mixin mdc-button__icon-contained_ { @include mdc-rtl-reflexive-property(margin, -4px, 8px); } @mixin mdc-button__icon-contained-trailing_ { @include mdc-rtl-reflexive-property(margin, 8px, -4px); } @mixin mdc-button--outlined_($query) { $feat-color: mdc-feature-create-target($query, color); $feat-structure: mdc-feature-create-target($query, structure); @include mdc-feature-targets($feat-structure) { border-style: solid; } &:disabled { @include mdc-feature-targets($feat-color) { border-color: $mdc-button-disabled-ink-color; } } } @mixin mdc-button--filled_($query) { $feat-color: mdc-feature-create-target($query, color); $feat-structure: mdc-feature-create-target($query, structure); @include mdc-button-horizontal-padding($mdc-button-contained-horizontal-padding, $query); &:disabled { @include mdc-feature-targets($feat-color) { background-color: rgba(mdc-theme-prop-value(on-surface), .12); color: $mdc-button-disabled-ink-color; } } } @mixin mdc-button--raised_($query) { $feat-animation: mdc-feature-create-target($query, animation); $feat-color: mdc-feature-create-target($query, color); @include mdc-elevation(2, $query: $query); &:hover, &:focus { @include mdc-elevation(4, $query: $query); } &:active { @include mdc-elevation(8, $query: $query); } &:disabled { @include mdc-elevation(0, $query: $query); } @include mdc-feature-targets($feat-animation) { transition: mdc-elevation-transition-value(); } }