Skip to content

Commit a782912

Browse files
committed
refactor(material/progress-spinner): change mat-progress-spinner to use MDC's token API
1 parent 9d09b34 commit a782912

File tree

5 files changed

+124
-53
lines changed

5 files changed

+124
-53
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
@use 'sass:map';
2+
@use '../../../theming/theming';
3+
@use '../../token-utils';
4+
5+
// The prefix used to generate the fully qualified name for tokens in this file.
6+
$prefix: (mdc, circular-progress);
7+
8+
// Tokens that can't be configured through Angular Material's current theming API,
9+
// but may be in a future version of the theming API.
10+
//
11+
// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`.
12+
// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in
13+
// our CSS.
14+
@function get-unthemable-tokens() {
15+
@return (
16+
// The thickness of the progress spinner's active indicator.
17+
active-indicator-width: 4px,
18+
// The the diameter of the spinner
19+
size: 48px,
20+
// =============================================================================================
21+
// = TOKENS NOT USED IN ANGULAR MATERIAL =
22+
// =============================================================================================
23+
// Angular Material does not support four color spinners
24+
four-color-active-indicator-one-color: null,
25+
// Angular Material does not support four color spinners
26+
four-color-active-indicator-two-color: null,
27+
// Angular Material does not support four color spinners
28+
four-color-active-indicator-three-color: null,
29+
// Angular Material does not support four color spinners
30+
four-color-active-indicator-four-color: null
31+
);
32+
}
33+
34+
// Tokens that can be configured through Angular Material's color theming API.
35+
@function get-color-tokens($config) {
36+
@return (
37+
// The color of the progress spinner's active indicator.
38+
active-indicator-color: theming.get-color-from-palette(map.get($config, primary))
39+
);
40+
}
41+
42+
// Tokens that can be configured through Angular Material's typography theming API.
43+
@function get-typography-tokens($config) {
44+
@return ();
45+
}
46+
47+
// Tokens that can be configured through Angular Material's density theming API.
48+
@function get-density-tokens($config) {
49+
@return ();
50+
}
51+
52+
// Combines the tokens generated by the above functions into a single map with placeholder values.
53+
// This is used to create token slots.
54+
@function get-token-slots() {
55+
@return map.merge(
56+
get-unthemable-tokens(),
57+
map.merge(
58+
get-color-tokens(token-utils.$placeholder-color-config),
59+
map.merge(
60+
get-typography-tokens(token-utils.$placeholder-typography-config),
61+
get-density-tokens(token-utils.$placeholder-density-config)
62+
)
63+
)
64+
);
65+
}

src/material/core/tokens/tests/test-validate-tokens.scss

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@
22
@use 'sass:map';
33
@use '@material/card/elevated-card-theme' as mdc-elevated-card-theme;
44
@use '@material/card/outlined-card-theme' as mdc-outlined-card-theme;
5+
@use '@material/circular-progress/circular-progress-theme' as mdc-circular-progress-theme;
56
@use '@material/list/list-theme' as mdc-list-theme;
67
@use '@material/theme/validate' as mdc-validate;
8+
@use '../m2/mdc/circular-progress' as tokens-mdc-circular-progress;
79
@use '../m2/mdc/elevated-card' as tokens-mdc-elevated-card;
810
@use '../m2/mdc/list' as tokens-mdc-list;
911
@use '../m2/mdc/outlined-card' as tokens-mdc-outlined-card;
12+
@use '@material/theme/validate' as mdc-validate;
1013

11-
@mixin validate-slots(
12-
$component,
13-
$slots,
14-
$reference
15-
) {
14+
@mixin validate-slots($component, $slots, $reference) {
1615
@debug 'Validating #{$component}...';
1716
// We don't care what the values are, just that every valid token is present in the slots map.
1817
// Specifically its ok if the token is explicitly mapped to `null`. We therefore replace all the
@@ -25,17 +24,23 @@
2524
}
2625

2726
@include validate-slots(
28-
$component: 'm2.mdc.list',
29-
$slots: tokens-mdc-list.get-token-slots(),
30-
$reference: mdc-list-theme.$light-theme
27+
$component: 'm2.mdc.list',
28+
$slots: tokens-mdc-list.get-token-slots(),
29+
$reference: mdc-list-theme.$light-theme
30+
);
31+
32+
@include validate-slots(
33+
$component: 'm2.mdc.circular-progress',
34+
$slots: tokens-mdc-circular-progress.get-token-slots(),
35+
$reference: mdc-circular-progress-theme.$light-theme
3136
);
3237
@include validate-slots(
33-
$component: 'm2.mdc.elevated-card',
34-
$slots: tokens-mdc-elevated-card.get-token-slots(),
35-
$reference: mdc-elevated-card-theme.$light-theme
38+
$component: 'm2.mdc.elevated-card',
39+
$slots: tokens-mdc-elevated-card.get-token-slots(),
40+
$reference: mdc-elevated-card-theme.$light-theme
3641
);
3742
@include validate-slots(
38-
$component: 'm2.mdc.outlined-card',
39-
$slots: tokens-mdc-outlined-card.get-token-slots(),
40-
$reference: mdc-outlined-card-theme.$light-theme
43+
$component: 'm2.mdc.outlined-card',
44+
$slots: tokens-mdc-outlined-card.get-token-slots(),
45+
$reference: mdc-outlined-card-theme.$light-theme
4146
);

src/material/progress-spinner/progress-spinner.scss

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,26 @@
1-
@use 'sass:map';
2-
@use '../core/mdc-helpers/mdc-helpers';
31
@use '@angular/cdk';
42
@use '@material/circular-progress/circular-progress' as mdc-circular-progress;
53
@use '@material/circular-progress/circular-progress-theme' as mdc-circular-progress-theme;
4+
@use '@material/theme/custom-properties' as mdc-custom-properties;
5+
@use '../core/tokens/m2/mdc/circular-progress' as m2-mdc-circular-progress;
66

7+
// The slots for tokens that will be configured in the theme can be emitted with no fallback.
8+
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
9+
$mdc-circular-progress-token-slots: m2-mdc-circular-progress.get-token-slots();
710

8-
@include mdc-helpers.disable-mdc-fallback-declarations {
9-
@include mdc-circular-progress.static-styles($query: mdc-helpers.$mdc-base-styles-query);
10-
}
11-
12-
.mat-mdc-progress-spinner {
13-
@include mdc-helpers.disable-mdc-fallback-declarations {
14-
@include mdc-circular-progress-theme.theme-styles(map.merge(
15-
mdc-circular-progress-theme.$light-theme,
16-
(
17-
active-indicator-color: transparent,
11+
// Add the MDC progress spinner static styles.
12+
@include mdc-circular-progress.static-styles();
1813

19-
// We don't support the multi color variant so we exclude these variables.
20-
four-color-active-indicator-four-color: null,
21-
four-color-active-indicator-one-color: null,
22-
four-color-active-indicator-three-color: null,
23-
four-color-active-indicator-two-color: null,
14+
// Add the official slots for the MDC circular progress.
15+
@include mdc-circular-progress-theme.theme-styles($mdc-circular-progress-token-slots);
2416

25-
// We currently size the element ourselves so we can exclude these styles as well.
26-
// TODO(crisbeto): look into reusing MDC's styles by binding to a CSS variable
27-
// in our own template.
28-
active-indicator-width: null,
29-
size: null,
30-
)
31-
));
17+
// Add default values for tokens that aren't outputted by the theming API.
18+
.mat-mdc-progress-spinner {
19+
@include mdc-circular-progress-theme.theme(m2-mdc-circular-progress.get-unthemable-tokens());
3220
}
21+
}
3322

23+
.mat-mdc-progress-spinner {
3424
// Explicitly set to `block` since the browser defaults custom elements to `inline`.
3525
display: block;
3626

@@ -43,7 +33,8 @@
4333
line-height: 0;
4434

4535
&._mat-animation-noopable {
46-
&, .mdc-circular-progress__determinate-circle {
36+
&,
37+
.mdc-circular-progress__determinate-circle {
4738
// The spinner itself has a transition on `opacity`.
4839
transition: none;
4940
}

src/material/progress-spinner/progress-spinner.spec.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,12 @@ describe('MDC-based MatProgressSpinner', () => {
123123
fixture.componentInstance.diameter = 32;
124124
fixture.detectChanges();
125125

126-
expect(parseInt(spinner.style.width))
126+
const {width, height} = spinner.getBoundingClientRect();
127+
128+
expect(width)
127129
.withContext('Expected the custom diameter to be applied to the host element width.')
128130
.toBe(32);
129-
expect(parseInt(spinner.style.height))
131+
expect(height)
130132
.withContext('Expected the custom diameter to be applied to the host element height.')
131133
.toBe(32);
132134
expect(parseInt(svgElement.clientWidth))
@@ -168,11 +170,12 @@ describe('MDC-based MatProgressSpinner', () => {
168170

169171
const spinner = fixture.debugElement.query(By.css('mat-progress-spinner'))!.nativeElement;
170172
const svgElement: HTMLElement = fixture.nativeElement.querySelector('svg');
173+
const {width, height} = spinner.getBoundingClientRect();
171174

172-
expect(parseFloat(spinner.style.width))
175+
expect(width)
173176
.withContext('Expected the custom diameter to be applied to the host element width.')
174177
.toBe(32.5);
175-
expect(parseFloat(spinner.style.height))
178+
expect(height)
176179
.withContext('Expected the custom diameter to be applied to the host element height.')
177180
.toBe(32.5);
178181
expect(Math.ceil(svgElement.clientWidth))
@@ -213,8 +216,10 @@ describe('MDC-based MatProgressSpinner', () => {
213216
fixture.componentInstance.strokeWidth = 40;
214217
fixture.detectChanges();
215218

216-
expect(element.style.width).toBe('100px');
217-
expect(element.style.height).toBe('100px');
219+
const {width, height} = element.getBoundingClientRect();
220+
221+
expect(width).toBe(100);
222+
expect(height).toBe(100);
218223
});
219224

220225
it('should not collapse the host element if the stroke width is less than the default', () => {
@@ -224,8 +229,10 @@ describe('MDC-based MatProgressSpinner', () => {
224229
fixture.componentInstance.strokeWidth = 5;
225230
fixture.detectChanges();
226231

227-
expect(element.style.width).toBe('100px');
228-
expect(element.style.height).toBe('100px');
232+
const {width, height} = element.getBoundingClientRect();
233+
234+
expect(width).toBe(100);
235+
expect(height).toBe(100);
229236
});
230237

231238
it('should set the color class on the mat-spinner', () => {
@@ -277,8 +284,10 @@ describe('MDC-based MatProgressSpinner', () => {
277284
expect(spinner.componentInstance.strokeWidth).toBe(11);
278285
expect(spinner.componentInstance.value).toBe(25);
279286

280-
expect(spinner.nativeElement.style.width).toBe('37px');
281-
expect(spinner.nativeElement.style.height).toBe('37px');
287+
const {width, height} = spinner.nativeElement.getBoundingClientRect();
288+
289+
expect(width).toBe(37);
290+
expect(height).toBe(37);
282291

283292
expect(svgElement.clientWidth).toBe(37);
284293
expect(svgElement.clientHeight).toBe(37);
@@ -290,8 +299,9 @@ describe('MDC-based MatProgressSpinner', () => {
290299
let spinner = fixture.debugElement.query(By.directive(MatProgressSpinner))!;
291300
spinner.componentInstance.diameter = 32;
292301
fixture.detectChanges();
293-
expect(spinner.nativeElement.style.width).toBe('32px');
294-
expect(spinner.nativeElement.style.height).toBe('32px');
302+
const {width, height} = spinner.nativeElement.getBoundingClientRect();
303+
expect(width).toBe(32);
304+
expect(height).toBe(32);
295305
});
296306

297307
it('should be able to set a default diameter', () => {

src/material/progress-spinner/progress-spinner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ const BASE_STROKE_WIDTH = 10;
8080
'tabindex': '-1',
8181
'[class._mat-animation-noopable]': `_noopAnimations`,
8282
'[class.mdc-circular-progress--indeterminate]': 'mode === "indeterminate"',
83-
'[style.width.px]': 'diameter',
84-
'[style.height.px]': 'diameter',
83+
'[style.--mdc-circular-progress-size]': 'diameter + "px"',
84+
'[style.--mdc-circular-progress-active-indicator-width]': 'diameter + "px"',
8585
'[attr.aria-valuemin]': '0',
8686
'[attr.aria-valuemax]': '100',
8787
'[attr.aria-valuenow]': 'mode === "determinate" ? value : null',

0 commit comments

Comments
 (0)