UNPKG

12.6 kBSCSSView Raw
1//
2// Copyright 2020 Google Inc.
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21//
22
23// Selector '.mdc-*' should only be used in this project.
24// stylelint-disable selector-class-pattern
25
26@use '@material/animation/animation';
27@use '@material/dom/mixins' as dom-mixins;
28@use '@material/elevation/mixins' as elevation-mixins;
29@use '@material/feature-targeting/feature-targeting';
30@use '@material/ripple/ripple';
31@use '@material/ripple/ripple-theme';
32@use '@material/rtl/mixins' as rtl-mixins;
33@use '@material/theme/theme-color';
34@use '@material/typography/typography';
35@use './slider-theme';
36
37// Thumb variables.
38$_thumb-ripple-size: 48px;
39$_thumb-size: 20px;
40$_value-indicator-caret-width: 6px;
41
42// Track variables.
43$_track-active-height: 6px;
44$_track-inactive-height: 4px;
45
46/// Core styles for slider component.
47@mixin core-styles($query: feature-targeting.all()) {
48 @include ripple($query: $query);
49 @include without-ripple($query: $query);
50}
51
52// This API is intended for use by frameworks that may want to separate the
53// ripple-related styles from the other slider styles.
54// It is recommended that most users use `core-styles` instead.
55@mixin without-ripple($query: feature-targeting.all()) {
56 $feat-animation: feature-targeting.create-target($query, animation);
57 $feat-color: feature-targeting.create-target($query, color);
58 $feat-structure: feature-targeting.create-target($query, structure);
59
60 .mdc-slider {
61 @include _track($query: $query);
62 @include _thumb($query: $query);
63 @include _tick-marks($query: $query);
64
65 @include feature-targeting.targets($feat-structure) {
66 cursor: pointer;
67 height: $_thumb-ripple-size;
68 margin: 0 ($_thumb-ripple-size / 2);
69 position: relative;
70 touch-action: pan-y;
71 }
72
73 &.mdc-slider--disabled {
74 @include _disabled($query: $query);
75 }
76
77 &--discrete {
78 .mdc-slider__thumb,
79 .mdc-slider__track--active_fill {
80 @include feature-targeting.targets($feat-animation) {
81 transition: transform 80ms ease;
82 }
83 }
84
85 @media (prefers-reduced-motion) {
86 .mdc-slider__thumb,
87 .mdc-slider__track--active_fill {
88 @include feature-targeting.targets($feat-animation) {
89 transition: none;
90 }
91 }
92 }
93 }
94 }
95
96 .mdc-slider__input {
97 @include feature-targeting.targets($feat-structure) {
98 cursor: pointer;
99 left: 0;
100 margin: 0;
101 height: 100%;
102 opacity: 0;
103 pointer-events: none;
104 position: absolute;
105 top: 0;
106 width: 100%;
107 }
108 }
109}
110
111// This API is intended for use by frameworks that may want to separate the
112// ripple-related styles from the other slider styles.
113// It is recommended that most users use `core-styles` instead.
114@mixin ripple($query: feature-targeting.all()) {
115 @include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE
116
117 .mdc-slider__thumb {
118 @include ripple.surface($query: $query);
119 @include ripple.radius-unbounded($query: $query);
120 @include ripple-theme.states($color: slider-theme.$color, $query: $query);
121 }
122}
123
124@mixin _track($query: feature-targeting.all()) {
125 $feat-structure: feature-targeting.create-target($query, structure);
126
127 .mdc-slider__track {
128 @include feature-targeting.targets($feat-structure) {
129 height: $_track-inactive-height;
130 position: absolute;
131 top: 50%;
132 transform: translateY(-50%);
133 width: 100%;
134 }
135 }
136
137 .mdc-slider__track--active,
138 .mdc-slider__track--inactive {
139 @include feature-targeting.targets($feat-structure) {
140 display: flex;
141 height: 100%;
142 position: absolute;
143 width: 100%;
144 }
145 }
146
147 .mdc-slider__track--active {
148 @include feature-targeting.targets($feat-structure) {
149 // Set border-radius on the outer `track--active` element, and apply
150 // transform: scale(...) to the inner `track--active_fill` element,
151 // such that the track grows/shrinks as needed, but the border-radius
152 // is not affected by the scaling.
153 border-radius: 3px;
154 height: $_track-active-height;
155 overflow: hidden;
156 top: ($_track-inactive-height - $_track-active-height) / 2;
157 }
158 }
159
160 .mdc-slider__track--active_fill {
161 @include feature-targeting.targets($feat-structure) {
162 // Use border rather than background-color to fill track, for HCM.
163 border-top: $_track-active-height solid;
164 box-sizing: border-box;
165 height: 100%;
166 width: 100%;
167 position: relative;
168 /* @noflip */
169 -webkit-transform-origin: left;
170 /* @noflip */
171 transform-origin: left;
172
173 @include rtl-mixins.rtl {
174 /* @noflip */
175 -webkit-transform-origin: right;
176 /* @noflip */
177 transform-origin: right;
178 }
179 }
180 }
181
182 .mdc-slider__track--inactive {
183 &::before {
184 @include dom-mixins.transparent-border($query: $query); // For HCM.
185 }
186
187 @include feature-targeting.targets($feat-structure) {
188 border-radius: 2px;
189 height: $_track-inactive-height;
190 left: 0;
191 top: 0;
192 }
193 }
194
195 @include slider-theme.track-active-color(
196 $color-or-map: (
197 default: slider-theme.$color,
198 disabled: slider-theme.$disabled-color,
199 ),
200 $query: $query
201 );
202 @include slider-theme.track-inactive-color(
203 $color-or-map: (
204 default: slider-theme.$color,
205 disabled: slider-theme.$disabled-color,
206 ),
207 $query: $query
208 );
209}
210
211@mixin _thumb($query: feature-targeting.all()) {
212 $feat-color: feature-targeting.create-target($query, color);
213 $feat-structure: feature-targeting.create-target($query, structure);
214
215 @include _value-indicator($query: $query);
216
217 .mdc-slider__thumb {
218 @include feature-targeting.targets($feat-structure) {
219 display: flex;
220 height: $_thumb-ripple-size;
221 /* @noflip */
222 left: -$_thumb-ripple-size / 2;
223 outline: none;
224 position: absolute;
225 user-select: none;
226 width: $_thumb-ripple-size;
227 }
228
229 &--top {
230 @include feature-targeting.targets($feat-structure) {
231 z-index: 1;
232 }
233 }
234
235 &--top .mdc-slider__thumb-knob,
236 &--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,
237 &--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob {
238 @include feature-targeting.targets($feat-structure) {
239 border: 1px solid;
240 box-sizing: content-box;
241 }
242
243 @include feature-targeting.targets($feat-color) {
244 border-color: #fff;
245 }
246 }
247 }
248
249 .mdc-slider__thumb-knob {
250 @include elevation-mixins.elevation($z-value: 1, $query: $query);
251
252 @include feature-targeting.targets($feat-structure) {
253 // Use border rather than background-color to fill thumb, for HCM.
254 border: $_thumb-size / 2 solid;
255 border-radius: 50%;
256 box-sizing: border-box;
257 height: $_thumb-size;
258 /* @noflip */
259 left: 50%;
260 position: absolute;
261 top: 50%;
262 transform: translate(-50%, -50%);
263 width: $_thumb-size;
264 }
265 }
266
267 @include slider-theme.thumb-color(
268 $color-or-map: (
269 default: slider-theme.$color,
270 disabled: slider-theme.$disabled-color,
271 ),
272 $query: $query
273 );
274 @include slider-theme.thumb-ripple-color(
275 $color: slider-theme.$color,
276 $query: $query
277 );
278}
279
280@mixin _tick-marks($query: feature-targeting.all()) {
281 $feat-structure: feature-targeting.create-target($query, structure);
282 $feat-color: feature-targeting.create-target($query, color);
283
284 .mdc-slider__tick-marks {
285 @include feature-targeting.targets($feat-structure) {
286 align-items: center;
287 box-sizing: border-box;
288 display: flex;
289 height: 100%;
290 justify-content: space-between;
291 padding: 0 1px;
292 position: absolute;
293 width: 100%;
294 }
295 }
296
297 .mdc-slider__tick-mark--active,
298 .mdc-slider__tick-mark--inactive {
299 @include feature-targeting.targets($feat-structure) {
300 border-radius: 50%;
301 height: 2px;
302 width: 2px;
303 }
304 }
305
306 @include slider-theme.tick-mark-active-color(
307 $color-or-map: (
308 default: slider-theme.$tick-mark-active-color,
309 disabled: on-primary,
310 ),
311 $query: $query
312 );
313 @include slider-theme.tick-mark-inactive-color(
314 $color-or-map: (
315 default: slider-theme.$tick-mark-inactive-color,
316 disabled: slider-theme.$disabled-color,
317 ),
318 $query: $query
319 );
320}
321
322@mixin _value-indicator($query: feature-targeting.all()) {
323 $feat-animation: feature-targeting.create-target($query, animation);
324 $feat-structure: feature-targeting.create-target($query, structure);
325
326 .mdc-slider__value-indicator-container {
327 @include feature-targeting.targets($feat-structure) {
328 bottom: $_thumb-ripple-size / 2 + $_thumb-size / 2 +
329 $_value-indicator-caret-width + 4px;
330 /* @noflip */
331 left: 50%;
332 pointer-events: none;
333 position: absolute;
334 transform: translateX(-50%);
335 }
336 }
337
338 .mdc-slider__value-indicator {
339 @include feature-targeting.targets($feat-animation) {
340 transition: animation.exit-permanent(transform, 100ms);
341 }
342
343 @include feature-targeting.targets($feat-structure) {
344 align-items: center;
345 border-radius: 4px;
346 display: flex;
347 height: 32px;
348 padding: 0 12px;
349 transform: scale(0);
350 transform-origin: bottom;
351 }
352
353 // Caret: https://css-tricks.com/snippets/css/css-triangle/
354 &::before {
355 @include feature-targeting.targets($feat-structure) {
356 border-left: $_value-indicator-caret-width solid transparent;
357 border-right: $_value-indicator-caret-width solid transparent;
358 border-top: $_value-indicator-caret-width solid;
359 bottom: -$_value-indicator-caret-width + 1;
360 content: '';
361 height: 0;
362 /* @noflip */
363 left: 50%;
364 position: absolute;
365 transform: translateX(-50%);
366 width: 0;
367 }
368 }
369
370 &::after {
371 @include dom-mixins.transparent-border($query: $query); // For HCM.
372 }
373 }
374
375 .mdc-slider__thumb--with-indicator {
376 .mdc-slider__value-indicator-container {
377 @include feature-targeting.targets($feat-structure) {
378 pointer-events: auto;
379 }
380 }
381
382 .mdc-slider__value-indicator {
383 @include feature-targeting.targets($feat-animation) {
384 transition: animation.enter(transform, 100ms);
385 }
386
387 @include feature-targeting.targets($feat-structure) {
388 transform: scale(1);
389 }
390 }
391 }
392
393 @media (prefers-reduced-motion) {
394 .mdc-slider__value-indicator,
395 .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator {
396 @include feature-targeting.targets($feat-animation) {
397 transition: none;
398 }
399 }
400 }
401
402 .mdc-slider__value-indicator-text {
403 @include typography.typography(subtitle2, $query);
404 }
405
406 @include slider-theme.value-indicator-color(
407 $color: slider-theme.$value-indicator-color,
408 $opacity: slider-theme.$value-indicator-opacity,
409 $query: $query
410 );
411 @include slider-theme.value-indicator-text-color(
412 $color: slider-theme.$value-indicator-text-color,
413 $query: $query
414 );
415}
416
417// Styles for slider in disabled state.
418@mixin _disabled($query: feature-targeting.all()) {
419 $feat-color: feature-targeting.create-target($query, color);
420 $feat-structure: feature-targeting.create-target($query, structure);
421
422 @include feature-targeting.targets($feat-color) {
423 opacity: 0.38;
424 }
425
426 @include feature-targeting.targets($feat-structure) {
427 cursor: auto;
428 }
429
430 .mdc-slider__thumb {
431 @include feature-targeting.targets($feat-structure) {
432 pointer-events: none;
433 }
434 }
435}