Skip to content

Commit 28eb736

Browse files
committed
refactor(material/radio): switch to tokens API
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 2604f15 commit 28eb736

File tree

8 files changed

+299
-195
lines changed

8 files changed

+299
-195
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: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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+
// = TOKENS NOT USED IN ANGULAR MATERIAL =
21+
// =============================================================================================
22+
selected-focus-state-layer-color: null,
23+
selected-focus-state-layer-opacity: null,
24+
selected-hover-state-layer-color: null,
25+
selected-hover-state-layer-opacity: null,
26+
selected-pressed-state-layer-color: null,
27+
selected-pressed-state-layer-opacity: null,
28+
unselected-focus-icon-color: null,
29+
unselected-focus-state-layer-color: null,
30+
unselected-focus-state-layer-opacity: null,
31+
unselected-hover-state-layer-color: null,
32+
unselected-hover-state-layer-opacity: null,
33+
unselected-pressed-state-layer-color: null,
34+
unselected-pressed-state-layer-opacity: null,
35+
);
36+
}
37+
38+
// Tokens that can be configured through Angular Material's color theming API.
39+
@function get-color-tokens($config) {
40+
$accent: map.get($config, accent);
41+
$is-dark: map.get($config, is-dark);
42+
$accent-color: theming.get-color-from-palette($accent, default);
43+
$on-surface: if($is-dark, #fff, #000);
44+
$icon-color: theming.get-color-from-palette(palette.$gray-palette, if($is-dark, 200, 900));
45+
46+
@return (
47+
disabled-selected-icon-color: $on-surface,
48+
disabled-unselected-icon-color: $on-surface,
49+
unselected-hover-icon-color: $icon-color,
50+
unselected-icon-color: rgba($on-surface, 0.54),
51+
unselected-pressed-icon-color: rgba($on-surface, 0.54),
52+
selected-focus-icon-color: $accent-color,
53+
selected-hover-icon-color: $accent-color,
54+
selected-icon-color: $accent-color,
55+
selected-pressed-icon-color: $accent-color,
56+
);
57+
}
58+
59+
// Tokens that can be configured through Angular Material's typography theming API.
60+
@function get-typography-tokens($config) {
61+
@return ();
62+
}
63+
64+
// Tokens that can be configured through Angular Material's density theming API.
65+
@function get-density-tokens($config) {
66+
$scale: theming.clamp-density($config, -3);
67+
68+
@return (
69+
// The diameter of the radio's ripple.
70+
state-layer-size: map.get((
71+
0: 40px,
72+
-1: 36px,
73+
-2: 32px,
74+
-3: 28px,
75+
), $scale)
76+
);
77+
}
78+
79+
// Combines the tokens generated by the above functions into a single map with placeholder values.
80+
// This is used to create token slots.
81+
@function get-token-slots() {
82+
@return token-utils.merge-all(
83+
get-unthemable-tokens(),
84+
get-color-tokens(token-utils.$placeholder-color-config),
85+
get-typography-tokens(token-utils.$placeholder-typography-config),
86+
get-density-tokens(token-utils.$placeholder-density-config)
87+
);
88+
}

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: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
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;
5+
@use '@material/theme/custom-properties' as mdc-custom-properties;
66

77
@use '../core/mdc-helpers/mdc-helpers';
88
@use '../core/tokens/m2/mdc/checkbox' as tokens-mdc-checkbox;
9-
@use '../radio/radio-private';
9+
@use '../core/tokens/m2/mdc/radio' as tokens-mdc-radio;
1010
@use './list-option-trailing-avatar-compat';
1111
@use './list-item-hcm-indicator';
1212

@@ -29,35 +29,27 @@
2929
}
3030
}
3131

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-
42-
// We can't use the MDC checkbox here directly, because this checkbox is purely
43-
// decorative and including the MDC one will bring in unnecessary JS.
44-
.mdc-checkbox {
45-
// MDC theme styles also include structural styles so we have to include the theme at least
46-
// once here. The values will be overwritten by our own theme file afterwards.
47-
@include mdc-checkbox-theme.theme-styles(tokens-mdc-checkbox.get-token-slots());
48-
}
49-
50-
// We can't use the MDC radio here directly, because this radio is purely
51-
// decorative and including the MDC one will bring in unnecessary JS.
52-
.mdc-radio {
53-
$config: map.merge(radio-private.$private-radio-theme-config, $without-ripple-config);
32+
@include mdc-custom-properties.configure(
33+
$emit-fallback-values: false,
34+
$emit-fallback-vars: false
35+
) {
36+
// We can't use the MDC checkbox here directly, because this checkbox is purely
37+
// decorative and including the MDC one will bring in unnecessary JS.
38+
.mdc-checkbox {
39+
// MDC theme styles also include structural styles so we have to include the theme at least
40+
// once here. The values will be overwritten by our own theme file afterwards.
41+
@include mdc-checkbox-theme.theme-styles(tokens-mdc-checkbox.get-token-slots());
42+
}
5443

55-
// MDC theme styles also include structural styles so we have to include the theme at least
56-
// once here. The values will be overwritten by our own theme file afterwards.
57-
@include mdc-radio-theme.theme-styles($config);
44+
// We can't use the MDC radio here directly, because this radio is purely
45+
// decorative and including the MDC one will bring in unnecessary JS.
46+
.mdc-radio {
47+
// MDC theme styles also include structural styles so we have to include the theme at least
48+
// once here. The values will be overwritten by our own theme file afterwards.
49+
@include mdc-radio-theme.theme-styles(tokens-mdc-radio.get-token-slots());
50+
}
5851
}
5952

60-
6153
// The internal checkbox/radio is purely decorative, but because it's an `input`, the user can
6254
// still focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role
6355
// 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)