// // Copyright 2020 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:math'; @use '@material/animation/animation'; @use '@material/dom/mixins' as dom-mixins; @use '@material/feature-targeting/feature-targeting'; @use '@material/ripple/ripple'; @use '@material/ripple/ripple-theme'; @use '@material/rtl/rtl'; @use '@material/theme/css'; @use '@material/theme/theme-color'; @use '@material/typography/typography'; @use './slider-theme'; // Thumb variables. $_thumb-ripple-size: 48px; $_thumb-size: 20px; $_value-indicator-caret-width: 6px; // Track variables. $_track-active-height: 6px; $_track-inactive-height: 4px; /// Core styles for slider component. @mixin core-styles($query: feature-targeting.all()) { @include ripple($query: $query); @include without-ripple($query: $query); } // This API is intended for use by frameworks that may want to separate the // ripple-related styles from the other slider styles. // It is recommended that most users use `core-styles` instead. @mixin without-ripple($query: feature-targeting.all()) { $feat-structure: feature-targeting.create-target($query, structure); @include static-styles($query: $query); .mdc-slider { @include slider-theme.theme-styles( slider-theme.$light-theme, $query: $query ); } } // This API is intended for use by frameworks that may want to separate the // ripple-related styles from the other slider styles. // It is recommended that most users use `core-styles` instead. @mixin ripple($query: feature-targeting.all()) { @include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE .mdc-slider__thumb { @include ripple.surface($query: $query); @include ripple.radius-unbounded($query: $query); @include ripple-theme.states($color: slider-theme.$color, $query: $query); } } @mixin static-styles($query: feature-targeting.all()) { $feat-animation: feature-targeting.create-target($query, animation); $feat-color: feature-targeting.create-target($query, color); $feat-structure: feature-targeting.create-target($query, structure); .mdc-slider { @include _track($query: $query); @include _thumb($query: $query); @include _tick-marks($query: $query); @include feature-targeting.targets($feat-structure) { cursor: pointer; height: $_thumb-ripple-size; margin: 0 math.div($_thumb-ripple-size, 2); position: relative; touch-action: pan-y; } &--discrete { .mdc-slider__thumb, .mdc-slider__track--active_fill { @include feature-targeting.targets($feat-animation) { transition: transform 80ms ease; } } @media (prefers-reduced-motion) { .mdc-slider__thumb, .mdc-slider__track--active_fill { @include feature-targeting.targets($feat-animation) { transition: none; } } } } } .mdc-slider--disabled { @include _disabled($query: $query); } .mdc-slider__input { $indent: 2px; $size: $_thumb-ripple-size - 2 * $indent; @include feature-targeting.targets($feat-structure) { cursor: pointer; left: $indent; margin: 0; height: $size; opacity: 0; pointer-events: none; position: absolute; top: $indent; width: $size; } } } @mixin _track($query: feature-targeting.all()) { $feat-structure: feature-targeting.create-target($query, structure); .mdc-slider__track { @include feature-targeting.targets($feat-structure) { position: absolute; top: 50%; transform: translateY(-50%); width: 100%; } } .mdc-slider__track--active, .mdc-slider__track--inactive { @include feature-targeting.targets($feat-structure) { display: flex; height: 100%; position: absolute; width: 100%; } } .mdc-slider__track--active { @include feature-targeting.targets($feat-structure) { overflow: hidden; } } .mdc-slider__track--active_fill { @include feature-targeting.targets($feat-structure) { // Use border rather than background-color to fill track, for HCM. border-top-style: solid; box-sizing: border-box; height: 100%; width: 100%; position: relative; @include rtl.ignore-next-line(); -webkit-transform-origin: left; @include rtl.ignore-next-line(); transform-origin: left; @include rtl.rtl { @include rtl.ignore-next-line(); -webkit-transform-origin: right; @include rtl.ignore-next-line(); transform-origin: right; } } } .mdc-slider__track--inactive { &::before { @include dom-mixins.transparent-border($query: $query); // For HCM. } @include feature-targeting.targets($feat-structure) { left: 0; top: 0; } } } @mixin _thumb($query: feature-targeting.all()) { $feat-color: feature-targeting.create-target($query, color); $feat-structure: feature-targeting.create-target($query, structure); @include _value-indicator($query: $query); .mdc-slider__thumb { @include feature-targeting.targets($feat-structure) { display: flex; @include rtl.ignore-next-line(); left: math.div(-$_thumb-ripple-size, 2); outline: none; position: absolute; user-select: none; height: $_thumb-ripple-size; width: $_thumb-ripple-size; } &--top { @include feature-targeting.targets($feat-structure) { z-index: 1; } } &--top .mdc-slider__thumb-knob, &--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob, &--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob { @include feature-targeting.targets($feat-structure) { border-style: solid; border-width: 1px; box-sizing: content-box; } } } .mdc-slider__thumb-knob { @include feature-targeting.targets($feat-structure) { box-sizing: border-box; @include rtl.ignore-next-line(); left: 50%; position: absolute; top: 50%; @include rtl.ignore-next-line(); transform: translate(-50%, -50%); } } } @mixin _tick-marks($query: feature-targeting.all()) { $feat-structure: feature-targeting.create-target($query, structure); $feat-color: feature-targeting.create-target($query, color); .mdc-slider__tick-marks { @include feature-targeting.targets($feat-structure) { align-items: center; box-sizing: border-box; display: flex; height: 100%; justify-content: space-between; padding: 0 1px; position: absolute; width: 100%; } } } @mixin _value-indicator($query: feature-targeting.all()) { $feat-animation: feature-targeting.create-target($query, animation); $feat-structure: feature-targeting.create-target($query, structure); .mdc-slider__value-indicator-container { @include feature-targeting.targets($feat-structure) { bottom: math.div($_thumb-ripple-size, 2) + math.div($_thumb-size, 2) + $_value-indicator-caret-width + 4px; @include css.declaration( left, var(--slider-value-indicator-container-left, 50%), 50%, $gss: (noflip: true) ); pointer-events: none; position: absolute; @include css.declaration( right, var(--slider-value-indicator-container-right), $gss: (noflip: true) ); @include css.declaration( transform, var(--slider-value-indicator-container-transform, translateX(-50%)), translateX(-50%), $gss: (noflip: true) ); } } .mdc-slider__value-indicator { @include feature-targeting.targets($feat-animation) { transition: animation.exit-permanent(transform, 100ms); } @include feature-targeting.targets($feat-structure) { align-items: center; border-radius: 4px; display: flex; height: 32px; padding: 0 12px; transform: scale(0); transform-origin: bottom; } // Caret: https://css-tricks.com/snippets/css/css-triangle/ &::before { @include feature-targeting.targets($feat-structure) { border-left: $_value-indicator-caret-width solid transparent; border-right: $_value-indicator-caret-width solid transparent; border-top: $_value-indicator-caret-width solid; bottom: -$_value-indicator-caret-width + 1; content: ''; height: 0; @include css.declaration( left, var(--slider-value-indicator-caret-left, 50%), 50%, $gss: (noflip: true) ); position: absolute; @include css.declaration( right, var(--slider-value-indicator-caret-right), $gss: (noflip: true) ); @include css.declaration( transform, var(--slider-value-indicator-caret-transform, translateX(-50%)), translateX(-50%), $gss: (noflip: true) ); width: 0; } } &::after { @include dom-mixins.transparent-border($query: $query); // For HCM. } } .mdc-slider__thumb--with-indicator { .mdc-slider__value-indicator-container { @include feature-targeting.targets($feat-structure) { pointer-events: auto; } } .mdc-slider__value-indicator { @include feature-targeting.targets($feat-animation) { transition: animation.enter(transform, 100ms); } @include feature-targeting.targets($feat-structure) { transform: scale(1); } } } @media (prefers-reduced-motion) { .mdc-slider__value-indicator, .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator { @include feature-targeting.targets($feat-animation) { transition: none; } } } } // Styles for slider in disabled state. @mixin _disabled($query: feature-targeting.all()) { $feat-structure: feature-targeting.create-target($query, structure); @include feature-targeting.targets($feat-structure) { cursor: auto; } .mdc-slider__thumb { @include feature-targeting.targets($feat-structure) { pointer-events: none; } } }