UNPKG

9.55 kBSCSSView Raw
1//
2// Copyright 2016 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// stylelint-disable selector-class-pattern --
24// Selector '.mdc-*' should only be used in this project.
25
26@use 'sass:map';
27@use '@material/animation/animation';
28@use '@material/dom/dom';
29@use '@material/feature-targeting/feature-targeting';
30@use '@material/ripple/ripple';
31@use '@material/ripple/ripple-theme';
32@use '@material/touch-target/mixins' as touch-target-mixins;
33@use '@material/touch-target/variables' as touch-target-variables;
34@use './radio-theme';
35@use '@material/focus-ring/focus-ring';
36
37$ripple-target: radio-theme.$ripple-target;
38
39///
40/// Radio core styles.
41///
42@mixin core-styles($query: feature-targeting.all()) {
43 @include without-ripple($query);
44 @include ripple($query);
45}
46
47@mixin static-styles($query: feature-targeting.all()) {
48 $feat-animation: feature-targeting.create-target($query, animation);
49 $feat-color: feature-targeting.create-target($query, color);
50 $feat-structure: feature-targeting.create-target($query, structure);
51
52 .mdc-radio {
53 @include feature-targeting.targets($feat-structure) {
54 display: inline-block;
55 position: relative;
56 flex: 0 0 auto;
57 box-sizing: content-box;
58 width: radio-theme.$icon-size;
59 height: radio-theme.$icon-size;
60 cursor: pointer;
61 /* @alternate */
62 will-change: opacity, transform, border-color, color;
63 }
64
65 // Container for radio circles and ripple.
66 &__background {
67 @include feature-targeting.targets($feat-structure) {
68 display: inline-block;
69 position: relative;
70 box-sizing: border-box;
71 width: radio-theme.$icon-size;
72 height: radio-theme.$icon-size;
73 }
74
75 &::before {
76 @include feature-targeting.targets($feat-structure) {
77 position: absolute;
78 transform: scale(0, 0);
79 border-radius: 50%;
80 opacity: 0;
81 pointer-events: none;
82 content: '';
83 }
84
85 @include feature-targeting.targets($feat-animation) {
86 transition: exit(opacity), exit(transform);
87 }
88 }
89 }
90
91 &__outer-circle {
92 @include feature-targeting.targets($feat-structure) {
93 position: absolute;
94 top: 0;
95 left: 0;
96 box-sizing: border-box;
97 width: 100%;
98 height: 100%;
99 border-width: 2px;
100 border-style: solid;
101 border-radius: 50%;
102 }
103
104 @include feature-targeting.targets($feat-animation) {
105 transition: exit(border-color);
106 }
107 }
108
109 &__inner-circle {
110 @include feature-targeting.targets($feat-structure) {
111 position: absolute;
112 top: 0;
113 left: 0;
114 box-sizing: border-box;
115 width: 100%;
116 height: 100%;
117 transform: scale(0, 0);
118 border-width: 10px;
119 border-style: solid;
120 border-radius: 50%;
121 }
122
123 @include feature-targeting.targets($feat-animation) {
124 transition: exit(transform), exit(border-color);
125 }
126 }
127
128 &__native-control {
129 @include feature-targeting.targets($feat-structure) {
130 position: absolute;
131 margin: 0;
132 padding: 0;
133 opacity: 0;
134 cursor: inherit;
135 z-index: 1;
136 }
137 }
138
139 &--touch {
140 @include touch-target-mixins.margin(
141 $component-height: radio-theme.$ripple-size,
142 $component-width: radio-theme.$ripple-size,
143 $query: $query
144 );
145 @include radio-theme.touch-target(
146 $size: touch-target-variables.$height,
147 $query: $query
148 );
149 }
150
151 @include ripple-theme.focus {
152 .mdc-radio__focus-ring {
153 @include focus-ring.focus-ring(
154 $container-outer-padding-vertical: 0,
155 $container-outer-padding-horizontal: 0,
156 $query: $query
157 );
158 }
159 }
160 }
161
162 .mdc-radio__native-control:checked,
163 .mdc-radio__native-control:disabled {
164 + .mdc-radio__background {
165 @include feature-targeting.targets($feat-animation) {
166 transition: enter(opacity), enter(transform);
167 }
168
169 .mdc-radio__outer-circle {
170 @include feature-targeting.targets($feat-animation) {
171 transition: enter(border-color);
172 }
173 }
174
175 .mdc-radio__inner-circle {
176 @include feature-targeting.targets($feat-animation) {
177 transition: enter(transform), enter(border-color);
178 }
179 }
180 }
181 }
182
183 .mdc-radio--disabled {
184 @include feature-targeting.targets($feat-structure) {
185 cursor: default;
186 pointer-events: none;
187 }
188 }
189
190 .mdc-radio__native-control:checked {
191 + .mdc-radio__background {
192 .mdc-radio__inner-circle {
193 @include feature-targeting.targets($feat-structure) {
194 transform: scale(0.5);
195 }
196
197 @include feature-targeting.targets($feat-animation) {
198 transition: enter(transform), enter(border-color);
199 }
200 }
201 }
202 }
203
204 .mdc-radio__native-control:disabled,
205 [aria-disabled='true'] .mdc-radio__native-control {
206 + .mdc-radio__background {
207 @include feature-targeting.targets($feat-structure) {
208 cursor: default;
209 }
210 }
211 }
212
213 .mdc-radio__native-control:focus {
214 + .mdc-radio__background::before {
215 @include feature-targeting.targets($feat-structure) {
216 transform: scale(1);
217 opacity: map.get(ripple-theme.$dark-ink-opacities, focus);
218 }
219
220 @include feature-targeting.targets($feat-animation) {
221 transition: enter(opacity), enter(transform);
222 }
223 }
224 }
225}
226
227// This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
228// radio styles. It is recommended that most users use `mdc-radio-core-styles` instead.
229@mixin without-ripple($query: feature-targeting.all()) {
230 // postcss-bem-linter: define radio
231 @include touch-target-mixins.wrapper($query); // COPYBARA_COMMENT_THIS_LINE
232
233 .mdc-radio {
234 @include radio-theme.unchecked-stroke-color(
235 radio-theme.$unchecked-color,
236 $query: $query
237 );
238 @include radio-theme.checked-stroke-color(
239 radio-theme.$baseline-theme-color,
240 $query: $query
241 );
242 @include radio-theme.ink-color(
243 radio-theme.$baseline-theme-color,
244 $query: $query
245 );
246 @include radio-theme.disabled-unchecked-stroke-color(
247 radio-theme.$disabled-circle-color,
248 $query: $query
249 );
250 @include radio-theme.disabled-checked-stroke-color(
251 radio-theme.$disabled-circle-color,
252 $query: $query
253 );
254 @include radio-theme.disabled-ink-color(
255 radio-theme.$disabled-circle-color,
256 $query: $query
257 );
258 @include radio-theme.focus-indicator-color(
259 radio-theme.$baseline-theme-color,
260 $query: $query
261 );
262 @include radio-theme.density(radio-theme.$density-scale, $query: $query);
263
264 @include dom.forced-colors-mode {
265 &.mdc-radio--disabled {
266 @include radio-theme.disabled-unchecked-stroke-color(
267 GrayText,
268 $query: $query
269 );
270 @include radio-theme.disabled-checked-stroke-color(
271 GrayText,
272 $query: $query
273 );
274 @include radio-theme.disabled-ink-color(GrayText, $query: $query);
275 }
276 }
277 }
278
279 @include static-styles($query: $query);
280 // postcss-bem-linter: end
281}
282
283// This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
284// radio styles. It is recommended that most users use `mdc-radio-core-styles` instead.
285@mixin ripple($query: feature-targeting.all()) {
286 $feat-structure: feature-targeting.create-target($query, structure);
287
288 @include ripple.common($query); // COPYBARA_COMMENT_THIS_LINE
289
290 .mdc-radio {
291 @include ripple.surface($query: $query, $ripple-target: $ripple-target);
292 @include ripple.radius-unbounded(
293 $query: $query,
294 $ripple-target: $ripple-target
295 );
296 @include ripple-theme.states(
297 $color: radio-theme.$baseline-theme-color,
298 $query: $query,
299 $ripple-target: $ripple-target
300 );
301
302 &.mdc-ripple-upgraded,
303 &.mdc-ripple-upgraded--background-focused {
304 .mdc-radio__background::before {
305 @include feature-targeting.targets($feat-structure) {
306 content: none;
307 }
308 }
309 }
310 }
311
312 #{$ripple-target} {
313 @include ripple.target-common($query: $query);
314 }
315}
316
317@function enter($name) {
318 @return animation.enter($name, radio-theme.$transition-duration);
319}
320
321@function exit($name) {
322 @return animation.exit-temporary($name, radio-theme.$transition-duration);
323}