Skip to content

Commit c4026fe

Browse files
authored
refactor(material/radio): switch to tokens API (#26876)
Switches the radio button component to use the new tokens API. Also fixes a place in the list where CSS variable fallbacks weren't disabled.
1 parent 5825d4a commit c4026fe

File tree

8 files changed

+287
-183
lines changed

8 files changed

+287
-183
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@use 'sass:map';
2+
@use '../../token-utils';
3+
@use '../../../theming/theming';
4+
5+
// The prefix used to generate the fully qualified name for tokens in this file.
6+
$prefix: (mat, radio);
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+
@function get-unthemable-tokens() {
11+
@return ();
12+
}
13+
14+
// Tokens that can be configured through Angular Material's color theming API.
15+
@function get-color-tokens($config) {
16+
$foreground: map.get($config, foreground);
17+
$is-dark: map.get($config, is-dark);
18+
$accent: map.get($config, accent);
19+
20+
@return (
21+
ripple-color: if($is-dark, #fff, #000),
22+
checked-ripple-color: theming.get-color-from-palette($accent, default),
23+
disabled-label-color: theming.get-color-from-palette($foreground, disabled-text),
24+
);
25+
}
26+
27+
// Tokens that can be configured through Angular Material's typography theming API.
28+
@function get-typography-tokens($config) {
29+
@return ();
30+
}
31+
32+
// Tokens that can be configured through Angular Material's density theming API.
33+
@function get-density-tokens($config) {
34+
@return ();
35+
}
36+
37+
// Combines the tokens generated by the above functions into a single map with placeholder values.
38+
// This is used to create token slots.
39+
@function get-token-slots() {
40+
@return token-utils.merge-all(
41+
get-unthemable-tokens(),
42+
get-color-tokens(token-utils.$placeholder-color-config),
43+
get-typography-tokens(token-utils.$placeholder-typography-config),
44+
get-density-tokens(token-utils.$placeholder-density-config)
45+
);
46+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
@use 'sass:map';
2+
@use '../../../theming/palette';
3+
@use '../../../theming/theming';
4+
@use '../../token-utils';
5+
6+
// The prefix used to generate the fully qualified name for tokens in this file.
7+
$prefix: (mdc, radio);
8+
9+
// Tokens that can't be configured through Angular Material's current theming API,
10+
// but may be in a future version of the theming API.
11+
//
12+
// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`.
13+
// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in
14+
// our CSS.
15+
@function get-unthemable-tokens() {
16+
@return (
17+
disabled-selected-icon-opacity: 0.38,
18+
disabled-unselected-icon-opacity: 0.38,
19+
20+
// This is specified both here and in the density tokens, because it
21+
// determines the size of the radio button itself and there are internal
22+
// tests who don't configure the theme correctly.
23+
state-layer-size: 40px,
24+
25+
// =============================================================================================
26+
// = TOKENS NOT USED IN ANGULAR MATERIAL =
27+
// =============================================================================================
28+
selected-focus-state-layer-color: null,
29+
selected-focus-state-layer-opacity: null,
30+
selected-hover-state-layer-color: null,
31+
selected-hover-state-layer-opacity: null,
32+
selected-pressed-state-layer-color: null,
33+
selected-pressed-state-layer-opacity: null,
34+
unselected-focus-icon-color: null,
35+
unselected-focus-state-layer-color: null,
36+
unselected-focus-state-layer-opacity: null,
37+
unselected-hover-state-layer-color: null,
38+
unselected-hover-state-layer-opacity: null,
39+
unselected-pressed-state-layer-color: null,
40+
unselected-pressed-state-layer-opacity: null,
41+
);
42+
}
43+
44+
// Tokens that can be configured through Angular Material's color theming API.
45+
@function get-color-tokens($config) {
46+
$accent: map.get($config, accent);
47+
$is-dark: map.get($config, is-dark);
48+
$accent-color: theming.get-color-from-palette($accent, default);
49+
$on-surface: if($is-dark, #fff, #000);
50+
$icon-color: theming.get-color-from-palette(palette.$gray-palette, if($is-dark, 200, 900));
51+
52+
@return (
53+
disabled-selected-icon-color: $on-surface,
54+
disabled-unselected-icon-color: $on-surface,
55+
unselected-hover-icon-color: $icon-color,
56+
unselected-icon-color: rgba($on-surface, 0.54),
57+
unselected-pressed-icon-color: rgba($on-surface, 0.54),
58+
selected-focus-icon-color: $accent-color,
59+
selected-hover-icon-color: $accent-color,
60+
selected-icon-color: $accent-color,
61+
selected-pressed-icon-color: $accent-color,
62+
);
63+
}
64+
65+
// Tokens that can be configured through Angular Material's typography theming API.
66+
@function get-typography-tokens($config) {
67+
@return ();
68+
}
69+
70+
// Tokens that can be configured through Angular Material's density theming API.
71+
@function get-density-tokens($config) {
72+
$scale: theming.clamp-density($config, -3);
73+
74+
@return (
75+
// The diameter of the radio's ripple.
76+
state-layer-size: map.get((
77+
0: 40px,
78+
-1: 36px,
79+
-2: 32px,
80+
-3: 28px,
81+
), $scale)
82+
);
83+
}
84+
85+
// Combines the tokens generated by the above functions into a single map with placeholder values.
86+
// This is used to create token slots.
87+
@function get-token-slots() {
88+
@return token-utils.merge-all(
89+
get-unthemable-tokens(),
90+
get-color-tokens(token-utils.$placeholder-color-config),
91+
get-typography-tokens(token-utils.$placeholder-typography-config),
92+
get-density-tokens(token-utils.$placeholder-density-config)
93+
);
94+
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
@use '@material/icon-button/icon-button-theme' as mdc-icon-button-theme;
99
@use '@material/linear-progress/linear-progress-theme' as mdc-linear-progress-theme;
1010
@use '@material/list/list-theme' as mdc-list-theme;
11+
@use '@material/radio/radio-theme' as mdc-radio-theme;
1112
@use '@material/theme/validate' as mdc-validate;
1213

1314
@use '../m2/mdc/circular-progress' as tokens-mdc-circular-progress;
@@ -17,6 +18,7 @@
1718
@use '../m2/mdc/linear-progress' as tokens-mdc-linear-progress;
1819
@use '../m2/mdc/list' as tokens-mdc-list;
1920
@use '../m2/mdc/outlined-card' as tokens-mdc-outlined-card;
21+
@use '../m2/mdc/radio' as tokens-mdc-radio;
2022

2123
@mixin validate-slots($component, $slots, $reference) {
2224
@debug 'Validating #{$component}...';
@@ -65,3 +67,8 @@
6567
$slots: tokens-mdc-linear-progress.get-token-slots(),
6668
$reference: mdc-linear-progress-theme.$light-theme
6769
);
70+
@include validate-slots(
71+
$component: 'm2.mdc.radio',
72+
$slots: tokens-mdc-radio.get-token-slots(),
73+
$reference: mdc-radio-theme.$light-theme
74+
);

src/material/list/_list-theme.scss

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,59 @@
11
@use 'sass:map';
22
@use '@material/list/evolution-mixins';
33
@use '@material/checkbox/checkbox-theme' as mdc-checkbox-theme;
4+
@use '@material/radio/radio-theme' as mdc-radio-theme;
45
@use '@material/list/list-theme' as mdc-list-theme;
56

67
@use '../core/theming/theming';
78
@use '../core/tokens/m2/mdc/checkbox' as tokens-mdc-checkbox;
9+
@use '../core/tokens/m2/mdc/radio' as tokens-mdc-radio;
810
@use '../core/tokens/m2/mdc/list' as tokens-mdc-list;
911
@use '../core/typography/typography';
1012
@use '../core/typography/typography-utils';
11-
@use '../core/mdc-helpers/mdc-helpers';
12-
@use '../radio/radio-private';
1313

1414
@mixin color($config-or-theme) {
1515
$config: theming.get-color-config($config-or-theme);
1616
$primary: map.get($config, primary);
1717
$accent: map.get($config, accent);
1818
$warn: map.get($config, warn);
1919
$mdc-list-color-tokens: tokens-mdc-list.get-color-tokens($config);
20+
$inner-control-primary: map.merge($config, (accent: $primary));
21+
$inner-control-accent: map.merge($config, (accent: $accent));
22+
$inner-control-warn: map.merge($config, (accent: $warn));
2023

2124

2225
// Add values for MDC list tokens.
2326
.mat-mdc-list-base {
2427
@include mdc-list-theme.theme($mdc-list-color-tokens);
2528
}
2629

27-
// TODO(mmalerba): This should use MDC radio's token API instead.
28-
@include mdc-helpers.using-mdc-theme($config) {
30+
.mdc-list-item__start,
31+
.mdc-list-item__end {
32+
@include mdc-radio-theme.theme(tokens-mdc-radio.get-color-tokens($inner-control-primary));
33+
}
34+
35+
.mat-accent {
2936
.mdc-list-item__start,
3037
.mdc-list-item__end {
31-
@include radio-private.private-radio-color($config, theming.get-color-from-palette($primary));
32-
}
33-
34-
.mat-accent {
35-
.mdc-list-item__start,
36-
.mdc-list-item__end {
37-
@include radio-private.private-radio-color(
38-
$config, theming.get-color-from-palette($accent));
39-
}
38+
@include mdc-radio-theme.theme(tokens-mdc-radio.get-color-tokens($inner-control-accent));
4039
}
40+
}
4141

42-
.mat-warn {
43-
.mdc-list-item__start,
44-
.mdc-list-item__end {
45-
@include radio-private.private-radio-color($config, theming.get-color-from-palette($warn));
46-
}
42+
.mat-warn {
43+
.mdc-list-item__start,
44+
.mdc-list-item__end {
45+
@include mdc-radio-theme.theme(tokens-mdc-radio.get-color-tokens($inner-control-warn));
4746
}
4847
}
4948

5049
.mat-mdc-list-option {
51-
$primary-config: map.merge($config, (accent: $primary));
52-
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($primary-config));
50+
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($inner-control-primary));
5351
}
5452
.mat-mdc-list-option.mat-accent {
55-
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($config));
53+
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($inner-control-accent));
5654
}
5755
.mat-mdc-list-option.mat-warn {
58-
$warn-config: map.merge($config, (accent: $warn));
59-
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($warn-config));
56+
@include mdc-checkbox-theme.theme(tokens-mdc-checkbox.get-color-tokens($inner-control-warn));
6057
}
6158

6259
// There is no token for activated color on nav list.

src/material/list/list-option.scss

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
@use 'sass:map';
21
@use '@material/checkbox/checkbox' as mdc-checkbox;
32
@use '@material/checkbox/checkbox-theme' as mdc-checkbox-theme;
43
@use '@material/radio/radio' as mdc-radio;
54
@use '@material/radio/radio-theme' as mdc-radio-theme;
65

76
@use '../core/mdc-helpers/mdc-helpers';
87
@use '../core/tokens/m2/mdc/checkbox' as tokens-mdc-checkbox;
9-
@use '../radio/radio-private';
8+
@use '../core/tokens/m2/mdc/radio' as tokens-mdc-radio;
109
@use './list-option-trailing-avatar-compat';
1110
@use './list-item-hcm-indicator';
1211

@@ -29,16 +28,6 @@
2928
}
3029
}
3130

32-
$without-ripple-config: (
33-
// Since this checkbox/radio isn't interactive, we can exclude the focus/hover/press styles.
34-
selected-focus-icon-color: null,
35-
selected-hover-icon-color: null,
36-
selected-pressed-icon-color: null,
37-
unselected-focus-icon-color: null,
38-
unselected-hover-icon-color: null,
39-
unselected-pressed-icon-color: null,
40-
);
41-
4231
// We can't use the MDC checkbox here directly, because this checkbox is purely
4332
// decorative and including the MDC one will bring in unnecessary JS.
4433
.mdc-checkbox {
@@ -50,14 +39,11 @@
5039
// We can't use the MDC radio here directly, because this radio is purely
5140
// decorative and including the MDC one will bring in unnecessary JS.
5241
.mdc-radio {
53-
$config: map.merge(radio-private.$private-radio-theme-config, $without-ripple-config);
54-
5542
// MDC theme styles also include structural styles so we have to include the theme at least
5643
// once here. The values will be overwritten by our own theme file afterwards.
57-
@include mdc-radio-theme.theme-styles($config);
44+
@include mdc-radio-theme.theme-styles(tokens-mdc-radio.get-token-slots());
5845
}
5946

60-
6147
// The internal checkbox/radio is purely decorative, but because it's an `input`, the user can
6248
// still focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role
6349
// which doesn't allow a nested `input`. We use `display: none` both to remove it from the tab

src/material/radio/_radio-private.scss

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)