UNPKG

10.4 kBSCSSView Raw
1//
2// Copyright 2018 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@use '@material/feature-targeting/feature-targeting';
24@use '@material/animation/functions' as animation-functions;
25@use '@material/button/button-theme';
26@use '@material/icon-button/icon-button-theme';
27@use '@material/ripple/ripple-theme';
28@use '@material/rtl/rtl';
29@use '@material/dom/mixins' as dom-mixins;
30@use '@material/typography/typography';
31@use '@material/elevation/mixins' as elevation-mixins;
32@use '@material/shape/mixins' as shape-mixins;
33@use '@material/theme/theme';
34@use './variables';
35
36@mixin core-styles($query: feature-targeting.all()) {
37 $feat-structure: feature-targeting.create-target($query, structure);
38 $feat-animation: feature-targeting.create-target($query, animation);
39
40 // postcss-bem-linter: define snackbar
41 .mdc-snackbar {
42 @include z-index(variables.$z-index, $query: $query);
43 @include viewport-margin(variables.$viewport-margin-narrow, $query: $query);
44
45 @include feature-targeting.targets($feat-structure) {
46 display: none;
47 position: fixed;
48 right: 0;
49 bottom: 0;
50 left: 0;
51 align-items: center;
52 justify-content: center;
53 box-sizing: border-box;
54
55 // Ignore mouse events on the root layout element.
56 pointer-events: none;
57
58 // For some reason, iOS Safari displays a tap highlight on the entire snackbar element.
59 // Mobile Safari only supports `rgba` values for this property; named values like
60 // `transparent` are ignored. From Apple's docs:
61 // > This property obeys the alpha value, if specified.
62 // > If you don’t specify an alpha value, Safari on iOS applies a default alpha value to the color.
63 // > To disable tap highlighting, set the alpha value to 0 (invisible).
64 // > If you set the alpha value to 1.0 (opaque), the element is not visible when tapped.
65 // See https://github.com/ben-eb/postcss-colormin/issues/1
66 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
67 }
68 }
69
70 @include fill-color(variables.$fill-color, $query: $query);
71 @include label-ink-color(variables.$label-ink-color, $query: $query);
72 @include min-width(variables.$min-width, $query: $query);
73 @include max-width(variables.$max-width, $query: $query);
74 @include elevation(variables.$elevation, $query: $query);
75 @include shape-radius(variables.$shape-radius, $query: $query);
76
77 .mdc-snackbar--opening,
78 .mdc-snackbar--open,
79 .mdc-snackbar--closing {
80 @include feature-targeting.targets($feat-structure) {
81 display: flex;
82 }
83 }
84
85 .mdc-snackbar--open .mdc-snackbar__label,
86 .mdc-snackbar--open .mdc-snackbar__actions {
87 @include feature-targeting.targets($feat-structure) {
88 visibility: visible;
89 }
90 }
91
92 .mdc-snackbar--leading {
93 @include position-leading($query: $query);
94 }
95
96 .mdc-snackbar--stacked {
97 @include layout-stacked($query: $query);
98 }
99
100 .mdc-snackbar__surface {
101 // 1px border around the snackbar surface for high contrast mode.
102 &::before {
103 @include dom-mixins.transparent-border($query: $query);
104 }
105
106 @include feature-targeting.targets($feat-structure) {
107 @include rtl.reflexive-property(padding, 0, variables.$padding);
108
109 display: flex;
110 align-items: center;
111 justify-content: flex-start;
112 box-sizing: border-box;
113 transform: scale(0.8);
114 opacity: 0;
115 }
116
117 .mdc-snackbar--open & {
118 @include feature-targeting.targets($feat-structure) {
119 transform: scale(1);
120 opacity: 1;
121 pointer-events: auto; // Allow mouse events on surface element while snackbar is open
122 }
123
124 @include feature-targeting.targets($feat-animation) {
125 transition: animation-functions.enter(
126 opacity,
127 variables.$enter-duration
128 ),
129 animation-functions.enter(transform, variables.$enter-duration);
130 }
131 }
132
133 .mdc-snackbar--closing & {
134 @include feature-targeting.targets($feat-structure) {
135 transform: scale(1);
136 }
137
138 @include feature-targeting.targets($feat-animation) {
139 transition: animation-functions.exit-permanent(
140 opacity,
141 variables.$exit-duration
142 );
143 }
144 }
145 }
146
147 .mdc-snackbar__label {
148 @include typography.typography(variables.$label-type-scale, $query: $query);
149
150 @include feature-targeting.targets($feat-structure) {
151 @include rtl.reflexive-property(padding, 16px, variables.$padding);
152
153 width: 100%;
154 flex-grow: 1;
155 box-sizing: border-box;
156 margin: 0;
157 visibility: hidden;
158
159 // 14px top/bottom padding needed to make the height 48px.
160 padding-top: 14px;
161 padding-bottom: 14px;
162 }
163 }
164
165 // Used to prevent visual jank when announcing label text to screen readers.
166 // See the `announce()` function in util.js for details.
167 .mdc-snackbar__label::before {
168 @include feature-targeting.targets($feat-structure) {
169 display: inline;
170 content: attr(data-mdc-snackbar-label-text);
171 }
172 }
173
174 .mdc-snackbar__actions {
175 @include feature-targeting.targets($feat-structure) {
176 display: flex;
177 flex-shrink: 0;
178 align-items: center;
179 box-sizing: border-box;
180 visibility: hidden;
181 }
182 }
183
184 .mdc-snackbar__action {
185 @include button-theme.ink-color(
186 variables.$action-ink-color,
187 $query: $query
188 );
189 @include ripple-theme.states(variables.$action-ink-color, $query: $query);
190 }
191
192 .mdc-snackbar__dismiss {
193 @include icon-button-theme.ink-color(
194 variables.$dismiss-ink-color,
195 $query: $query
196 );
197 }
198
199 // Two selectors are needed to increase specificity above `.material-icons`.
200 // stylelint-disable-next-line selector-class-pattern
201 .mdc-snackbar__dismiss.mdc-snackbar__dismiss {
202 @include icon-button-theme.size(
203 variables.$dismiss-button-size,
204 $query: $query
205 );
206 @include feature-targeting.targets($feat-structure) {
207 font-size: variables.$dismiss-icon-size;
208 }
209 }
210
211 .mdc-snackbar__action + .mdc-snackbar__dismiss {
212 @include feature-targeting.targets($feat-structure) {
213 @include rtl.reflexive-property(margin, variables.$padding, 0);
214 }
215 }
216 // postcss-bem-linter: end
217}
218
219@mixin fill-color($color, $query: feature-targeting.all()) {
220 $feat-color: feature-targeting.create-target($query, color);
221
222 .mdc-snackbar__surface {
223 @include feature-targeting.targets($feat-color) {
224 @include theme.property(background-color, $color);
225 }
226 }
227}
228
229@mixin label-ink-color($color, $query: feature-targeting.all()) {
230 $feat-color: feature-targeting.create-target($query, color);
231
232 .mdc-snackbar__label {
233 @include feature-targeting.targets($feat-color) {
234 @include theme.property(color, $color);
235 }
236 }
237}
238
239@mixin shape-radius(
240 $radius,
241 $rtl-reflexive: false,
242 $query: feature-targeting.all()
243) {
244 .mdc-snackbar__surface {
245 @include shape-mixins.radius($radius, $rtl-reflexive, $query: $query);
246 }
247}
248
249@mixin min-width(
250 $min-width,
251 $mobile-breakpoint: variables.$mobile-breakpoint,
252 $query: feature-targeting.all()
253) {
254 $feat-structure: feature-targeting.create-target($query, structure);
255
256 .mdc-snackbar__surface {
257 @include feature-targeting.targets($feat-structure) {
258 min-width: $min-width;
259
260 // The first media query ensures that snackbars are always 100% width on mobile devices, as required by the spec.
261 // The second media query prevents snackbars from being wider than the viewport for large min-width values.
262 @media (max-width: $mobile-breakpoint), (max-width: $min-width) {
263 min-width: 100%;
264 }
265 }
266 }
267}
268
269@mixin max-width($max-width, $query: feature-targeting.all()) {
270 $feat-structure: feature-targeting.create-target($query, structure);
271
272 .mdc-snackbar__surface {
273 @include feature-targeting.targets($feat-structure) {
274 max-width: $max-width;
275 }
276 }
277}
278
279@mixin elevation($z-index, $query: feature-targeting.all()) {
280 .mdc-snackbar__surface {
281 @include elevation-mixins.elevation($z-index, $query: $query);
282 }
283}
284
285@mixin viewport-margin($margin, $query: feature-targeting.all()) {
286 $feat-structure: feature-targeting.create-target($query, structure);
287
288 @include feature-targeting.targets($feat-structure) {
289 margin: $margin;
290 }
291}
292
293@mixin z-index($z-index, $query: feature-targeting.all()) {
294 $feat-structure: feature-targeting.create-target($query, structure);
295
296 @include feature-targeting.targets($feat-structure) {
297 z-index: $z-index;
298 }
299}
300
301@mixin position-leading($query: feature-targeting.all()) {
302 $feat-structure: feature-targeting.create-target($query, structure);
303
304 @include feature-targeting.targets($feat-structure) {
305 justify-content: flex-start;
306 }
307}
308
309@mixin layout-stacked($query: feature-targeting.all()) {
310 $feat-structure: feature-targeting.create-target($query, structure);
311
312 .mdc-snackbar__label {
313 @include feature-targeting.targets($feat-structure) {
314 @include rtl.reflexive-property(padding, 16px, 8px);
315 padding-bottom: 12px;
316 }
317 }
318
319 .mdc-snackbar__surface {
320 @include feature-targeting.targets($feat-structure) {
321 flex-direction: column;
322 align-items: flex-start;
323 }
324 }
325
326 .mdc-snackbar__actions {
327 @include feature-targeting.targets($feat-structure) {
328 align-self: flex-end;
329 margin-bottom: variables.$padding;
330 }
331 }
332}