UNPKG

11.8 kBSCSSView Raw
1// Copyright 2017 Google Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21// stylelint-disable no-unknown-animations --
22// Animations keyframes are included in `keyframes.scss`.
23// stylelint-disable selector-class-pattern --
24// Selector '.mdc-*' should only be used in this project.
25
26@use 'sass:string';
27@use '@material/animation/functions' as animation-functions;
28@use '@material/dom/dom';
29@use '@material/feature-targeting/feature-targeting';
30@use '@material/rtl/rtl';
31@use '@material/theme/theme';
32@use '@material/theme/theme-color';
33@use './variables';
34@use './keyframes';
35
36//
37// Public
38//
39
40@mixin core-styles($query: feature-targeting.all()) {
41 $feat-structure: feature-targeting.create-target($query, structure);
42 $feat-animation: feature-targeting.create-target($query, animation);
43
44 @include feature-targeting.targets($feat-animation) {
45 @include keyframes.primary-indeterminate-translate-keyframes_;
46 @include keyframes.primary-indeterminate-scale-keyframes_;
47 @include keyframes.secondary-indeterminate-translate-keyframes_;
48 @include keyframes.secondary-indeterminate-scale-keyframes_;
49 @include keyframes.buffering-keyframes_;
50 @include keyframes.primary-indeterminate-translate-reverse-keyframes_;
51 @include keyframes.secondary-indeterminate-translate-reverse-keyframes_;
52 @include keyframes.buffering-reverse-keyframes_;
53 }
54
55 .mdc-linear-progress {
56 @include feature-targeting.targets($feat-structure) {
57 position: relative;
58 width: 100%;
59 transform: translateZ(0);
60 // Create a border around the bar in Windows High Contrast Mode.
61 outline: 1px solid transparent;
62 overflow: hidden;
63
64 @include dom.forced-colors-mode($exclude-ie11: true) {
65 outline-color: CanvasText;
66 }
67 }
68
69 @include feature-targeting.targets($feat-animation) {
70 transition: animation-functions.exit-temporary(opacity, 250ms);
71 }
72
73 &__bar {
74 @include feature-targeting.targets($feat-structure) {
75 position: absolute;
76 width: 100%;
77 height: 100%;
78 animation: none;
79 transform-origin: top left;
80 }
81
82 @include feature-targeting.targets($feat-animation) {
83 transition: animation-functions.exit-temporary(transform, 250ms);
84 }
85 }
86
87 &__bar-inner {
88 @include feature-targeting.targets($feat-structure) {
89 display: inline-block;
90 position: absolute;
91 width: 100%;
92 animation: none;
93 // border-top is used rather than background-color to ensure that the
94 // bar is visible in Windows High Contrast Mode.
95 border-top-style: solid;
96 }
97 }
98
99 &__buffer {
100 @include feature-targeting.targets($feat-structure) {
101 display: flex;
102 position: absolute;
103 width: 100%;
104 height: 100%;
105 }
106 }
107
108 &__buffer-dots {
109 @include feature-targeting.targets($feat-structure) {
110 background-repeat: repeat-x;
111 // background-size: 10px variables.$height;
112 flex: auto;
113 transform: rotate(180deg);
114 }
115
116 @include feature-targeting.targets($feat-animation) {
117 animation: mdc-linear-progress-buffering 250ms infinite linear;
118 }
119 }
120
121 &__buffer-bar {
122 @include feature-targeting.targets($feat-structure) {
123 flex: 0 1 100%;
124 }
125
126 @include feature-targeting.targets($feat-animation) {
127 transition: animation-functions.exit-temporary(flex-basis, 250ms);
128 }
129 }
130
131 &__primary-bar {
132 @include feature-targeting.targets($feat-structure) {
133 transform: scaleX(0);
134 }
135 }
136
137 &__secondary-bar {
138 @include feature-targeting.targets($feat-structure) {
139 display: none;
140 }
141 }
142
143 @include indeterminate_($query: $query);
144
145 @include rtl.rtl() {
146 // The rtl() mixin does not account for nested `dir` attributes. Set
147 // `dir` attribute on root to take highest priority.
148 &:not([dir='ltr']) {
149 @include _rtl-styles($query: $query);
150 }
151 }
152
153 &--closed {
154 @include feature-targeting.targets($feat-structure) {
155 opacity: 0;
156 }
157 }
158
159 &--closed-animation-off {
160 .mdc-linear-progress__buffer-dots {
161 @include feature-targeting.targets($feat-animation) {
162 animation: none;
163 }
164 }
165
166 &.mdc-linear-progress--indeterminate {
167 .mdc-linear-progress__bar,
168 .mdc-linear-progress__bar .mdc-linear-progress__bar-inner {
169 @include feature-targeting.targets($feat-animation) {
170 animation: none;
171 }
172 }
173 }
174 }
175 }
176
177 @at-root {
178 @include bar-color(primary, $query: $query);
179 @include buffer-color(variables.$baseline-buffer-color, $query: $query);
180 @include track-height(variables.$height, $query: $query);
181 }
182}
183
184@mixin bar-color($color, $query: feature-targeting.all()) {
185 $feat-color: feature-targeting.create-target($query, color);
186
187 .mdc-linear-progress__bar-inner {
188 @include feature-targeting.targets($feat-color) {
189 // Border is used rather than background-color to ensure that the
190 // bar is visible in Windows High Contrast Mode.
191 @include theme.property(border-color, $color);
192 }
193 }
194}
195
196@mixin buffer-color($color, $query: feature-targeting.all()) {
197 // We need to escape the '#' character as "%23" for SVG because '#' is a reserved character in URIs.
198 $color-value-for-css: theme-color.prop-value($color);
199 $color-value-for-svg: str-replace_(
200 string.unquote('#{$color-value-for-css}'),
201 '#',
202 '%23'
203 );
204 $feat-color: feature-targeting.create-target($query, color);
205
206 .mdc-linear-progress__buffer-dots {
207 @include feature-targeting.targets($feat-color) {
208 // SVG is optimized for data URI (https://codepen.io/tigt/post/optimizing-svgs-in-data-uris)
209 // stylelint-disable-next-line function-url-quotes
210 background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='#{$color-value-for-svg}'/%3E%3C/svg%3E");
211 }
212 }
213
214 .mdc-linear-progress__buffer-bar {
215 @include feature-targeting.targets($feat-color) {
216 background-color: $color-value-for-css;
217 }
218 }
219}
220
221@mixin track-height($height, $query: feature-targeting.all()) {
222 $feat-structure: feature-targeting.create-target($query, structure);
223 .mdc-linear-progress {
224 @include feature-targeting.targets($feat-structure) {
225 height: $height;
226 }
227
228 &__bar-inner {
229 @include feature-targeting.targets($feat-structure) {
230 border-top-width: $height;
231 }
232 }
233
234 &__buffer-dots {
235 @include feature-targeting.targets($feat-structure) {
236 background-size: 10px $height;
237 }
238 }
239 }
240}
241
242//
243// Private
244//
245
246@mixin indeterminate_($query: feature-targeting.all()) {
247 $feat-structure: feature-targeting.create-target($query, structure);
248 $feat-animation: feature-targeting.create-target($query, animation);
249
250 &--indeterminate {
251 .mdc-linear-progress__bar {
252 @include feature-targeting.targets($feat-structure) {
253 transition: none;
254 }
255 }
256
257 .mdc-linear-progress__primary-bar {
258 @include feature-targeting.targets($feat-structure) {
259 left: -145.166611%;
260 }
261 }
262
263 .mdc-linear-progress__secondary-bar {
264 @include feature-targeting.targets($feat-structure) {
265 left: -54.888891%;
266 display: block;
267 }
268 }
269
270 &.mdc-linear-progress--animation-ready {
271 .mdc-linear-progress__primary-bar {
272 @include feature-targeting.targets($feat-animation) {
273 animation: mdc-linear-progress-primary-indeterminate-translate 2s
274 infinite linear;
275 }
276
277 > .mdc-linear-progress__bar-inner {
278 @include feature-targeting.targets($feat-animation) {
279 animation: mdc-linear-progress-primary-indeterminate-scale 2s
280 infinite linear;
281 }
282 }
283 }
284
285 .mdc-linear-progress__secondary-bar {
286 @include feature-targeting.targets($feat-animation) {
287 animation: mdc-linear-progress-secondary-indeterminate-translate 2s
288 infinite linear;
289 }
290
291 > .mdc-linear-progress__bar-inner {
292 @include feature-targeting.targets($feat-animation) {
293 animation: mdc-linear-progress-secondary-indeterminate-scale 2s
294 infinite linear;
295 }
296 }
297 }
298 }
299 }
300}
301
302@mixin _rtl-styles($query: $query) {
303 $feat-structure: feature-targeting.create-target($query, structure);
304 $feat-animation: feature-targeting.create-target($query, animation);
305
306 .mdc-linear-progress__bar {
307 @include feature-targeting.targets($feat-structure) {
308 @include rtl.ignore-next-line();
309 right: 0;
310 @include rtl.ignore-next-line();
311 -webkit-transform-origin: center right;
312 @include rtl.ignore-next-line();
313 transform-origin: center right;
314 }
315 }
316
317 &.mdc-linear-progress--animation-ready {
318 .mdc-linear-progress__primary-bar {
319 @include feature-targeting.targets($feat-animation) {
320 animation-name: mdc-linear-progress-primary-indeterminate-translate-reverse;
321 }
322 }
323
324 .mdc-linear-progress__secondary-bar {
325 @include feature-targeting.targets($feat-animation) {
326 animation-name: mdc-linear-progress-secondary-indeterminate-translate-reverse;
327 }
328 }
329 }
330
331 .mdc-linear-progress__buffer-dots {
332 @include feature-targeting.targets($feat-animation) {
333 animation: mdc-linear-progress-buffering-reverse 250ms infinite linear;
334 }
335
336 @include feature-targeting.targets($feat-structure) {
337 transform: rotate(0);
338 }
339 }
340
341 &.mdc-linear-progress--indeterminate {
342 .mdc-linear-progress__primary-bar {
343 @include feature-targeting.targets($feat-structure) {
344 @include rtl.ignore-next-line();
345 right: -145.166611%;
346 @include rtl.ignore-next-line();
347 left: auto;
348 }
349 }
350
351 .mdc-linear-progress__secondary-bar {
352 @include feature-targeting.targets($feat-structure) {
353 @include rtl.ignore-next-line();
354 right: -54.888891%;
355 @include rtl.ignore-next-line();
356 left: auto;
357 }
358 }
359 }
360}
361
362// Based on https://css-tricks.com/snippets/sass/str-replace-function/
363@function str-replace_($string, $search, $replace) {
364 $index: string.index($string, $search);
365
366 @if $index {
367 $head: string.slice($string, 1, $index - 1);
368 $tail: str-replace_(
369 string.slice($string, $index + string.length($search)),
370 $search,
371 $replace
372 );
373
374 @return $head + $replace + $tail;
375 }
376
377 @return $string;
378}