UNPKG

11.1 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/feature-targeting/feature-targeting';
29@use '@material/rtl/rtl';
30@use '@material/theme/theme';
31@use '@material/theme/theme-color';
32@use './variables';
33@use './keyframes';
34
35//
36// Public
37//
38
39@mixin core-styles($query: feature-targeting.all()) {
40 $feat-structure: feature-targeting.create-target($query, structure);
41 $feat-animation: feature-targeting.create-target($query, animation);
42
43 @include feature-targeting.targets($feat-animation) {
44 @include keyframes.primary-indeterminate-translate-keyframes_;
45 @include keyframes.primary-indeterminate-scale-keyframes_;
46 @include keyframes.secondary-indeterminate-translate-keyframes_;
47 @include keyframes.secondary-indeterminate-scale-keyframes_;
48 @include keyframes.buffering-keyframes_;
49 @include keyframes.primary-indeterminate-translate-reverse-keyframes_;
50 @include keyframes.secondary-indeterminate-translate-reverse-keyframes_;
51 @include keyframes.buffering-reverse-keyframes_;
52 }
53
54 .mdc-linear-progress {
55 @include feature-targeting.targets($feat-structure) {
56 position: relative;
57 width: 100%;
58 height: variables.$height;
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
65 @include feature-targeting.targets($feat-animation) {
66 transition: animation-functions.exit-temporary(opacity, 250ms);
67 }
68
69 &__bar {
70 @include feature-targeting.targets($feat-structure) {
71 position: absolute;
72 width: 100%;
73 height: 100%;
74 animation: none;
75 transform-origin: top left;
76 }
77
78 @include feature-targeting.targets($feat-animation) {
79 transition: animation-functions.exit-temporary(transform, 250ms);
80 }
81 }
82
83 &__bar-inner {
84 @include feature-targeting.targets($feat-structure) {
85 display: inline-block;
86 position: absolute;
87 width: 100%;
88 animation: none;
89 // border-top is used rather than background-color to ensure that the
90 // bar is visible in Windows High Contrast Mode.
91 border-top: variables.$height solid;
92 }
93 }
94
95 &__buffer {
96 @include feature-targeting.targets($feat-structure) {
97 display: flex;
98 position: absolute;
99 width: 100%;
100 height: 100%;
101 }
102 }
103
104 &__buffer-dots {
105 @include feature-targeting.targets($feat-structure) {
106 background-repeat: repeat-x;
107 background-size: 10px variables.$height;
108 flex: auto;
109 transform: rotate(180deg);
110 }
111
112 @include feature-targeting.targets($feat-animation) {
113 animation: mdc-linear-progress-buffering 250ms infinite linear;
114 }
115 }
116
117 &__buffer-bar {
118 @include feature-targeting.targets($feat-structure) {
119 flex: 0 1 100%;
120 }
121
122 @include feature-targeting.targets($feat-animation) {
123 transition: animation-functions.exit-temporary(flex-basis, 250ms);
124 }
125 }
126
127 &__primary-bar {
128 @include feature-targeting.targets($feat-structure) {
129 transform: scaleX(0);
130 }
131 }
132
133 &__secondary-bar {
134 @include feature-targeting.targets($feat-structure) {
135 display: none;
136 }
137 }
138
139 @include indeterminate_($query: $query);
140
141 @include rtl.rtl() {
142 // The rtl() mixin does not account for nested `dir` attributes. Set
143 // `dir` attribute on root to take highest priority.
144 &:not([dir='ltr']) {
145 @include _rtl-styles($query: $query);
146 }
147 }
148
149 &--closed {
150 @include feature-targeting.targets($feat-structure) {
151 opacity: 0;
152 }
153 }
154
155 &--closed-animation-off {
156 .mdc-linear-progress__buffer-dots {
157 @include feature-targeting.targets($feat-animation) {
158 animation: none;
159 }
160 }
161
162 &.mdc-linear-progress--indeterminate {
163 .mdc-linear-progress__bar,
164 .mdc-linear-progress__bar .mdc-linear-progress__bar-inner {
165 @include feature-targeting.targets($feat-animation) {
166 animation: none;
167 }
168 }
169 }
170 }
171 }
172
173 @at-root {
174 @include bar-color(primary, $query: $query);
175 @include buffer-color(variables.$baseline-buffer-color, $query: $query);
176 }
177}
178
179@mixin bar-color($color, $query: feature-targeting.all()) {
180 $feat-color: feature-targeting.create-target($query, color);
181
182 .mdc-linear-progress__bar-inner {
183 @include feature-targeting.targets($feat-color) {
184 // Border is used rather than background-color to ensure that the
185 // bar is visible in Windows High Contrast Mode.
186 @include theme.property(border-color, $color);
187 }
188 }
189}
190
191@mixin buffer-color($color, $query: feature-targeting.all()) {
192 // We need to escape the '#' character as "%23" for SVG because '#' is a reserved character in URIs.
193 $color-value-for-css: theme-color.prop-value($color);
194 $color-value-for-svg: str-replace_(
195 string.unquote('#{$color-value-for-css}'),
196 '#',
197 '%23'
198 );
199 $feat-color: feature-targeting.create-target($query, color);
200
201 .mdc-linear-progress__buffer-dots {
202 @include feature-targeting.targets($feat-color) {
203 // SVG is optimized for data URI (https://codepen.io/tigt/post/optimizing-svgs-in-data-uris)
204 // stylelint-disable-next-line function-url-quotes
205 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");
206 }
207 }
208
209 .mdc-linear-progress__buffer-bar {
210 @include feature-targeting.targets($feat-color) {
211 background-color: $color-value-for-css;
212 }
213 }
214}
215
216//
217// Private
218//
219
220@mixin indeterminate_($query: feature-targeting.all()) {
221 $feat-structure: feature-targeting.create-target($query, structure);
222 $feat-animation: feature-targeting.create-target($query, animation);
223
224 &--indeterminate {
225 .mdc-linear-progress__bar {
226 @include feature-targeting.targets($feat-structure) {
227 transition: none;
228 }
229 }
230
231 .mdc-linear-progress__primary-bar {
232 @include feature-targeting.targets($feat-structure) {
233 left: -145.166611%;
234 }
235 }
236
237 .mdc-linear-progress__secondary-bar {
238 @include feature-targeting.targets($feat-structure) {
239 left: -54.888891%;
240 display: block;
241 }
242 }
243
244 &.mdc-linear-progress--animation-ready {
245 .mdc-linear-progress__primary-bar {
246 @include feature-targeting.targets($feat-animation) {
247 animation: mdc-linear-progress-primary-indeterminate-translate 2s
248 infinite linear;
249 }
250
251 > .mdc-linear-progress__bar-inner {
252 @include feature-targeting.targets($feat-animation) {
253 animation: mdc-linear-progress-primary-indeterminate-scale 2s
254 infinite linear;
255 }
256 }
257 }
258
259 .mdc-linear-progress__secondary-bar {
260 @include feature-targeting.targets($feat-animation) {
261 animation: mdc-linear-progress-secondary-indeterminate-translate 2s
262 infinite linear;
263 }
264
265 > .mdc-linear-progress__bar-inner {
266 @include feature-targeting.targets($feat-animation) {
267 animation: mdc-linear-progress-secondary-indeterminate-scale 2s
268 infinite linear;
269 }
270 }
271 }
272 }
273 }
274}
275
276@mixin _rtl-styles($query: $query) {
277 $feat-structure: feature-targeting.create-target($query, structure);
278 $feat-animation: feature-targeting.create-target($query, animation);
279
280 .mdc-linear-progress__bar {
281 @include feature-targeting.targets($feat-structure) {
282 @include rtl.ignore-next-line();
283 right: 0;
284 @include rtl.ignore-next-line();
285 -webkit-transform-origin: center right;
286 @include rtl.ignore-next-line();
287 transform-origin: center right;
288 }
289 }
290
291 &.mdc-linear-progress--animation-ready {
292 .mdc-linear-progress__primary-bar {
293 @include feature-targeting.targets($feat-animation) {
294 animation-name: mdc-linear-progress-primary-indeterminate-translate-reverse;
295 }
296 }
297
298 .mdc-linear-progress__secondary-bar {
299 @include feature-targeting.targets($feat-animation) {
300 animation-name: mdc-linear-progress-secondary-indeterminate-translate-reverse;
301 }
302 }
303 }
304
305 .mdc-linear-progress__buffer-dots {
306 @include feature-targeting.targets($feat-animation) {
307 animation: mdc-linear-progress-buffering-reverse 250ms infinite linear;
308 }
309
310 @include feature-targeting.targets($feat-structure) {
311 transform: rotate(0);
312 }
313 }
314
315 &.mdc-linear-progress--indeterminate {
316 .mdc-linear-progress__primary-bar {
317 @include feature-targeting.targets($feat-structure) {
318 @include rtl.ignore-next-line();
319 right: -145.166611%;
320 @include rtl.ignore-next-line();
321 left: auto;
322 }
323 }
324
325 .mdc-linear-progress__secondary-bar {
326 @include feature-targeting.targets($feat-structure) {
327 @include rtl.ignore-next-line();
328 right: -54.888891%;
329 @include rtl.ignore-next-line();
330 left: auto;
331 }
332 }
333 }
334}
335
336// Based on https://css-tricks.com/snippets/sass/str-replace-function/
337@function str-replace_($string, $search, $replace) {
338 $index: string.index($string, $search);
339
340 @if $index {
341 $head: string.slice($string, 1, $index - 1);
342 $tail: str-replace_(
343 string.slice($string, $index + string.length($search)),
344 $search,
345 $replace
346 );
347
348 @return $head + $replace + $tail;
349 }
350
351 @return $string;
352}