| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- //
- // Copyright 2021 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:color';
- @use 'sass:map';
- @use 'sass:meta';
- @use '@material/density/density';
- @use '@material/dom/dom';
- @use '@material/elevation/elevation-theme';
- @use '@material/ripple/ripple-theme';
- @use '@material/theme/color-palette';
- @use '@material/theme/custom-properties';
- @use '@material/theme/keys';
- @use '@material/theme/shadow-dom';
- @use '@material/theme/state';
- @use '@material/theme/theme-color';
- @use '@material/theme/theme';
- @use '@material/tokens/resolvers';
- @use '@material/shape/shape';
- @use './switch';
- $_density-config: (
- size: (
- minimum: 28px,
- default: 48px,
- maximum: 48px,
- ),
- );
- $_hairline: color-palette.$grey-300;
- $_inverse-primary: color.scale(
- theme-color.prop-value(primary),
- $lightness: 75%
- );
- $_on-surface: color-palette.$grey-800;
- $_on-surface-variant: color-palette.$grey-700;
- $_on-surface-state-content: color-palette.$grey-900;
- $_primary-state-content: color.scale(
- theme-color.prop-value(primary),
- $blackness: 50%
- );
- /// TODO: Change to private when MWC has better access
- /// @access private
- $selectors: (
- disabled: ':disabled',
- focus: ':focus',
- hover: ':hover',
- pressed: ':active',
- selected: '.mdc-switch--selected',
- unselected: '.mdc-switch--unselected',
- );
- $light-theme: (
- disabled-handle-elevation: 0,
- disabled-handle-opacity: 0.38,
- disabled-selected-handle-color: $_on-surface,
- disabled-selected-icon-color: on-primary,
- disabled-selected-icon-opacity: 0.38,
- disabled-selected-track-color: $_on-surface,
- disabled-track-opacity: 0.12,
- disabled-unselected-handle-color: $_on-surface,
- disabled-unselected-icon-color: on-primary,
- disabled-unselected-icon-opacity: 0.38,
- disabled-unselected-track-color: $_on-surface,
- handle-elevation: 1,
- handle-height: 20px,
- handle-shadow-color: elevation-theme.$baseline-color,
- handle-shape: 10px,
- handle-surface-color: surface,
- handle-width: 20px,
- selected-focus-handle-color: $_primary-state-content,
- selected-focus-state-layer-color: primary,
- selected-focus-state-layer-opacity: 0.12,
- selected-focus-track-color: $_inverse-primary,
- selected-handle-color: primary,
- selected-hover-handle-color: $_primary-state-content,
- selected-hover-state-layer-color: primary,
- selected-hover-state-layer-opacity: 0.04,
- selected-hover-track-color: $_inverse-primary,
- selected-icon-color: on-primary,
- selected-icon-size: 18px,
- selected-pressed-handle-color: $_primary-state-content,
- selected-pressed-state-layer-color: primary,
- selected-pressed-state-layer-opacity: 0.1,
- selected-pressed-track-color: $_inverse-primary,
- selected-track-color: $_inverse-primary,
- state-layer-size: 48px,
- track-height: 14px,
- track-shape: 7px,
- track-width: 36px,
- unselected-focus-handle-color: $_on-surface-state-content,
- unselected-focus-state-layer-color: $_on-surface,
- unselected-focus-state-layer-opacity: 0.12,
- unselected-focus-track-color: $_hairline,
- unselected-handle-color: $_on-surface-variant,
- unselected-hover-handle-color: $_on-surface-state-content,
- unselected-hover-state-layer-color: $_on-surface,
- unselected-hover-state-layer-opacity: 0.04,
- unselected-hover-track-color: $_hairline,
- unselected-icon-color: on-primary,
- unselected-icon-size: 18px,
- unselected-pressed-handle-color: $_on-surface-state-content,
- unselected-pressed-state-layer-color: $_on-surface,
- unselected-pressed-state-layer-opacity: 0.1,
- unselected-pressed-track-color: $_hairline,
- unselected-track-color: $_hairline,
- );
- $forced-colors-theme: (
- disabled-handle-opacity: 1,
- disabled-selected-icon-color: GrayText,
- disabled-selected-icon-opacity: 1,
- disabled-track-opacity: 1,
- disabled-unselected-icon-color: GrayText,
- disabled-unselected-icon-opacity: 1,
- selected-icon-color: ButtonText,
- unselected-icon-color: ButtonText,
- );
- @function density($density-scale) {
- $size: density.prop-value(
- $density-config: $_density-config,
- $density-scale: $density-scale,
- $property-name: size,
- );
- @return (state-layer-size: $size);
- }
- @mixin theme($theme, $resolvers: resolvers.$material) {
- @include theme.validate-theme($light-theme, $theme);
- // TODO(b/185172301): replace with improved feature targeting
- // IE11 Fallback
- @if shadow-dom.$css-selector-fallback-declarations {
- @include custom-properties.configure($emit-custom-properties: false) {
- @include dom.ie11-support {
- @include theme-styles($theme, $resolvers: $resolvers);
- }
- }
- }
- $theme: _resolve-theme($theme, $resolvers);
- @include keys.declare-custom-properties($theme, switch);
- }
- @function _resolve-theme($theme, $resolvers) {
- @return map.merge(
- $theme,
- _resolve-theme-handle-elevation(
- $theme,
- map.get($resolvers, elevation),
- disabled-handle-elevation,
- handle-elevation
- )
- );
- }
- @function _resolve-theme-handle-elevation($theme, $resolver, $keys...) {
- @if $resolver == null {
- @return $theme;
- }
- @each $key in $keys {
- // Resolve the value for each state key.
- $resolved-value: meta.call(
- $resolver,
- $elevation: map.get($theme, $key),
- $shadow-color: map.get($theme, handle-shadow-color)
- );
- // Update the theme with the resolved value.
- $theme: map.set($theme, $key, $resolved-value);
- }
- @return $theme;
- }
- @mixin theme-styles($theme, $resolvers: resolvers.$material) {
- @include theme.validate-theme-styles($light-theme, $theme);
- $theme: keys.create-theme-properties($theme, switch);
- @include _selected-handle-color(
- (
- default: map.get($theme, selected-handle-color),
- disabled: map.get($theme, disabled-selected-handle-color),
- focus: map.get($theme, selected-focus-handle-color),
- hover: map.get($theme, selected-hover-handle-color),
- pressed: map.get($theme, selected-pressed-handle-color),
- )
- );
- @include _unselected-handle-color(
- (
- default: map.get($theme, unselected-handle-color),
- disabled: map.get($theme, disabled-unselected-handle-color),
- focus: map.get($theme, unselected-focus-handle-color),
- hover: map.get($theme, unselected-hover-handle-color),
- pressed: map.get($theme, unselected-pressed-handle-color),
- )
- );
- @include _handle-surface-color(map.get($theme, handle-surface-color));
- @include _handle-elevation(
- map.get($resolvers, elevation),
- map.get($theme, handle-shadow-color),
- (
- default: map.get($theme, handle-elevation),
- disabled: map.get($theme, disabled-handle-elevation),
- )
- );
- @include _handle-height(map.get($theme, handle-height));
- @include _handle-opacity(
- (
- disabled: map.get($theme, disabled-handle-opacity),
- )
- );
- @include _handle-shape(map.get($theme, handle-shape));
- @include _handle-width(map.get($theme, handle-width));
- @include _selected-icon-color(
- (
- default: map.get($theme, selected-icon-color),
- disabled: map.get($theme, disabled-selected-icon-color),
- )
- );
- @include _unselected-icon-color(
- (
- default: map.get($theme, unselected-icon-color),
- disabled: map.get($theme, disabled-unselected-icon-color),
- )
- );
- @include _selected-icon-opacity(
- (
- disabled: map.get($theme, disabled-selected-icon-opacity),
- )
- );
- @include _unselected-icon-opacity(
- (
- disabled: map.get($theme, disabled-unselected-icon-opacity),
- )
- );
- @include _selected-icon-size(map.get($theme, selected-icon-size));
- @include _unselected-icon-size(map.get($theme, unselected-icon-size));
- @include _selected-ripple-color(
- (
- focus: map.get($theme, selected-focus-state-layer-color),
- hover: map.get($theme, selected-hover-state-layer-color),
- pressed: map.get($theme, selected-pressed-state-layer-color),
- )
- );
- @include _unselected-ripple-color(
- (
- focus: map.get($theme, unselected-focus-state-layer-color),
- hover: map.get($theme, unselected-hover-state-layer-color),
- pressed: map.get($theme, unselected-pressed-state-layer-color),
- )
- );
- @include _selected-ripple-opacity(
- (
- focus: map.get($theme, selected-focus-state-layer-opacity),
- hover: map.get($theme, selected-hover-state-layer-opacity),
- pressed: map.get($theme, selected-pressed-state-layer-opacity),
- )
- );
- @include _unselected-ripple-opacity(
- (
- focus: map.get($theme, unselected-focus-state-layer-opacity),
- hover: map.get($theme, unselected-hover-state-layer-opacity),
- pressed: map.get($theme, unselected-pressed-state-layer-opacity),
- )
- );
- @include _state-layer-size(map.get($theme, state-layer-size));
- @include _track-height(map.get($theme, track-height));
- @include _track-opacity(
- (
- disabled: map.get($theme, disabled-track-opacity),
- )
- );
- @include _track-selected-color(
- (
- default: map.get($theme, selected-track-color),
- disabled: map.get($theme, disabled-selected-track-color),
- focus: map.get($theme, selected-focus-track-color),
- hover: map.get($theme, selected-hover-track-color),
- pressed: map.get($theme, selected-pressed-track-color),
- )
- );
- @include _track-unselected-color(
- (
- default: map.get($theme, unselected-track-color),
- disabled: map.get($theme, disabled-unselected-track-color),
- focus: map.get($theme, unselected-focus-track-color),
- hover: map.get($theme, unselected-hover-track-color),
- pressed: map.get($theme, unselected-pressed-track-color),
- )
- );
- @include _track-shape(map.get($theme, track-shape));
- @include _track-width(map.get($theme, track-width));
- }
- @mixin _handle-color($colors) {
- @include state.default($selectors) {
- @include _set-handle-color(state.get-default-state($colors));
- }
- @include state.hover($selectors) {
- @include _set-handle-color(state.get-hover-state($colors));
- }
- @include state.focus($selectors) {
- @include _set-handle-color(state.get-focus-state($colors));
- }
- @include state.pressed($selectors) {
- @include _set-handle-color(state.get-pressed-state($colors));
- }
- @include state.disabled($selectors) {
- @include _set-handle-color(state.get-disabled-state($colors));
- }
- }
- @mixin _set-handle-color($color) {
- .mdc-switch__handle {
- &::after {
- @include theme.property(background, $color);
- }
- }
- }
- @mixin _selected-handle-color($colors) {
- @include state.selected($selectors) {
- @include _handle-color($colors);
- }
- }
- @mixin _unselected-handle-color($colors) {
- @include state.unselected($selectors) {
- @include _handle-color($colors);
- }
- }
- @mixin _handle-surface-color($color) {
- .mdc-switch__handle {
- // Sets the surface color for the handle. This is used so that when an
- // opacity is applied to the "main" handle color, it will not bleed through
- // and appear transparent on top of the track.
- &::before {
- @include theme.property(background, $color);
- }
- }
- }
- @mixin _handle-elevation($resolver, $shadow-color, $elevations) {
- @include state.default($selectors) {
- @include _set-handle-elevation(
- $resolver,
- $elevation: state.get-default-state($elevations),
- $shadow-color: $shadow-color
- );
- }
- @include state.disabled($selectors) {
- @include _set-handle-elevation(
- $resolver,
- $elevation: state.get-disabled-state($elevations),
- $shadow-color: $shadow-color
- );
- }
- }
- @mixin _set-handle-elevation($resolver, $args...) {
- .mdc-switch__shadow {
- @include elevation-theme.with-resolver($resolver, $args...);
- }
- }
- @mixin _handle-height($height) {
- .mdc-switch__focus-ring-wrapper,
- .mdc-switch__handle {
- @include theme.property(height, $height);
- }
- }
- @mixin _handle-opacity($opacities) {
- @include state.disabled($selectors) {
- @include _set-handle-opacity(state.get-disabled-state($opacities));
- }
- }
- @mixin _set-handle-opacity($opacity) {
- .mdc-switch__handle {
- // Only apply to the ::after pseudo element, which is the handle's "main"
- // color. The ::before pseudo element is the surface color, which prevents
- // the handle from bleeding through on the track.
- &::after {
- @include theme.property(opacity, $opacity);
- }
- }
- }
- @mixin _handle-shape($shape) {
- .mdc-switch__handle {
- @include shape.radius($shape);
- }
- }
- @mixin _handle-width($width) {
- .mdc-switch__handle {
- @include theme.property(width, $width);
- }
- .mdc-switch__handle-track {
- @include theme.property(
- width,
- 'calc(100% - width)',
- $replace: (width: $width)
- );
- }
- }
- @mixin _icon-color($colors) {
- @include state.default($selectors) {
- @include _set-icon-color(state.get-default-state($colors));
- }
- @include state.disabled($selectors) {
- @include _set-icon-color(state.get-disabled-state($colors));
- }
- }
- @mixin _set-icon-color($color) {
- .mdc-switch__icon {
- @include theme.property(fill, $color);
- }
- }
- @mixin _selected-icon-color($colors) {
- @include state.selected($selectors) {
- @include _icon-color($colors);
- }
- }
- @mixin _unselected-icon-color($colors) {
- @include state.unselected($selectors) {
- @include _icon-color($colors);
- }
- }
- @mixin _icon-opacity($opacities) {
- @include state.disabled($selectors) {
- @include _set-icon-opacity(state.get-disabled-state($opacities));
- }
- }
- @mixin _set-icon-opacity($opacity) {
- .mdc-switch__icons {
- @include theme.property(opacity, $opacity);
- }
- }
- @mixin _selected-icon-opacity($opacities) {
- @include state.selected($selectors) {
- @include _icon-opacity($opacities);
- }
- }
- @mixin _unselected-icon-opacity($opacities) {
- @include state.unselected($selectors) {
- @include _icon-opacity($opacities);
- }
- }
- @mixin _icon-size($size) {
- .mdc-switch__icon {
- @include theme.property(width, $size);
- @include theme.property(height, $size);
- }
- }
- @mixin _selected-icon-size($size) {
- @include state.selected($selectors) {
- @include _icon-size($size);
- }
- }
- @mixin _unselected-icon-size($size) {
- @include state.unselected($selectors) {
- @include _icon-size($size);
- }
- }
- @mixin _ripple-color($colors) {
- @include state.independent-elements(pressed) {
- @include state.hover($selectors) {
- @include ripple-theme.states-base-color(
- state.get-hover-state($colors),
- $ripple-target: switch.$ripple-target
- );
- }
- @include state.focus($selectors) {
- @include ripple-theme.states-base-color(
- state.get-focus-state($colors),
- $ripple-target: switch.$ripple-target
- );
- }
- @include state.pressed($selectors) {
- @include ripple-theme.states-base-color(
- state.get-pressed-state($colors),
- $ripple-target: switch.$ripple-target
- );
- }
- }
- }
- @mixin _selected-ripple-color($colors) {
- @include state.selected($selectors) {
- @include _ripple-color($colors);
- }
- }
- @mixin _unselected-ripple-color($colors) {
- @include state.unselected($selectors) {
- @include _ripple-color($colors);
- }
- }
- @mixin _ripple-opacity($opacities) {
- @include state.independent-elements(pressed) {
- @include state.hover($selectors) {
- @include ripple-theme.states-hover-opacity(
- state.get-hover-state($opacities),
- $ripple-target: switch.$ripple-target
- );
- }
- @include state.focus($selectors) {
- @include ripple-theme.states-focus-opacity(
- state.get-focus-state($opacities),
- $ripple-target: switch.$ripple-target
- );
- }
- @include state.pressed($selectors) {
- @include ripple-theme.states-press-opacity(
- state.get-pressed-state($opacities),
- $ripple-target: switch.$ripple-target
- );
- }
- }
- }
- @mixin _selected-ripple-opacity($opacities) {
- @include state.selected($selectors) {
- @include _ripple-opacity($opacities);
- }
- }
- @mixin _unselected-ripple-opacity($opacities) {
- @include state.unselected($selectors) {
- @include _ripple-opacity($opacities);
- }
- }
- @mixin _state-layer-size($size) {
- .mdc-switch__ripple {
- @include theme.property(height, $size);
- @include theme.property(width, $size);
- }
- }
- @mixin _track-height($height) {
- .mdc-switch__track {
- @include theme.property(height, $height);
- }
- }
- @mixin _track-opacity($opacities) {
- @include state.disabled($selectors) {
- @include _set-track-opacity(state.get-disabled-state($opacities));
- }
- }
- @mixin _set-track-opacity($opacity) {
- .mdc-switch__track {
- @include theme.property(opacity, $opacity);
- }
- }
- @mixin _track-selected-color($colors) {
- @include state.default($selectors) {
- @include _set-track-selected-color(state.get-default-state($colors));
- }
- @include state.hover($selectors) {
- @include _set-track-selected-color(state.get-hover-state($colors));
- }
- @include state.focus($selectors) {
- @include _set-track-selected-color(state.get-focus-state($colors));
- }
- @include state.pressed($selectors) {
- @include _set-track-selected-color(state.get-pressed-state($colors));
- }
- @include state.disabled($selectors) {
- @include _set-track-selected-color(state.get-disabled-state($colors));
- }
- }
- @mixin _set-track-selected-color($color) {
- .mdc-switch__track::after {
- @include theme.property(background, $color);
- }
- }
- @mixin _track-unselected-color($colors) {
- @include state.default($selectors) {
- @include _set-track-unselected-color(state.get-default-state($colors));
- }
- @include state.hover($selectors) {
- @include _set-track-unselected-color(state.get-hover-state($colors));
- }
- @include state.focus($selectors) {
- @include _set-track-unselected-color(state.get-focus-state($colors));
- }
- @include state.pressed($selectors) {
- @include _set-track-unselected-color(state.get-pressed-state($colors));
- }
- @include state.disabled($selectors) {
- @include _set-track-unselected-color(state.get-disabled-state($colors));
- }
- }
- @mixin _set-track-unselected-color($color) {
- .mdc-switch__track::before {
- @include theme.property(background, $color);
- }
- }
- @mixin _track-shape($shape) {
- .mdc-switch__track {
- @include shape.radius($shape);
- }
- }
- @mixin _track-width($width) {
- @include theme.property(width, $width);
- }
|