Skip to content

Commit 48a988a

Browse files
authored
refactor(material/button): switch to tokens theming API (#27784)
* refactor(material/button): switch to tokens theming API * fixup! refactor(material/button): switch to tokens theming API * fixup! refactor(material/button): switch to tokens theming API * fixup! refactor(material/button): switch to tokens theming API * fixup! refactor(material/button): switch to tokens theming API * fixup! refactor(material/button): switch to tokens theming API
1 parent 6d40517 commit 48a988a

File tree

4 files changed

+166
-44
lines changed

4 files changed

+166
-44
lines changed

src/material/button/_button-theme.scss

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,19 @@
1111
@use '../core/theming/theming';
1212
@use '../core/theming/inspection';
1313
@use '../core/typography/typography';
14+
@use '../core/tokens/m2/mdc/button-filled' as tokens-mdc-button-filled;
15+
16+
@function on-color($theme, $palette) {
17+
$is-dark: inspection.get-theme-type($theme) == dark;
18+
@return if(mdc-helpers.variable-safe-contrast-tone($palette, $is-dark) == 'dark', #000, #fff);
19+
}
1420

1521
@mixin _button-variant($color) {
1622
@include mdc-button-text-theme.theme((
1723
label-text-color: $color,
1824
));
1925
}
2026

21-
@mixin _unelevated-button-variant($foreground, $background) {
22-
@include mdc-button-filled-theme.theme((
23-
container-color: $background,
24-
label-text-color: $foreground,
25-
));
26-
}
27-
2827
@mixin _raised-button-variant($foreground, $background) {
2928
@include mdc-button-protected-theme.theme((
3029
container-color: $background,
@@ -79,35 +78,6 @@
7978
}
8079
}
8180

82-
.mat-mdc-unelevated-button {
83-
&.mat-unthemed {
84-
@include _unelevated-button-variant($on-surface, $surface);
85-
}
86-
87-
&.mat-primary {
88-
@include _unelevated-button-variant($on-primary, $primary);
89-
}
90-
91-
&.mat-accent {
92-
@include _unelevated-button-variant($on-secondary, $secondary);
93-
}
94-
95-
&.mat-warn {
96-
@include _unelevated-button-variant($on-error, $error);
97-
}
98-
99-
@include button-theme-private.apply-disabled-style() {
100-
@include mdc-button-filled-theme.theme((
101-
// We need to pass both the disabled and enabled values, because the enabled
102-
// ones apply to anchors while the disabled ones are for buttons.
103-
disabled-container-color: $disabled-container-color,
104-
disabled-label-text-color: $disabled-ink-color,
105-
container-color: $disabled-container-color,
106-
label-text-color: $disabled-ink-color,
107-
));
108-
}
109-
}
110-
11181
.mat-mdc-raised-button {
11282
&.mat-unthemed {
11383
@include _raised-button-variant($on-surface, $surface);
@@ -180,6 +150,52 @@
180150
@include button-theme-private.ripple-theme-styles($theme, true);
181151
}
182152
}
153+
154+
.mat-mdc-unelevated-button {
155+
$surface: inspection.get-theme-color($theme, background, card);
156+
$primary: inspection.get-theme-color($theme, primary);
157+
$accent: inspection.get-theme-color($theme, accent);
158+
$error: inspection.get-theme-color($theme, warn);
159+
160+
$on-surface: on-color($theme, $surface);
161+
$on-primary: on-color($theme, $primary);
162+
$on-accent: on-color($theme, $accent);
163+
$on-error: on-color($theme, $error);
164+
165+
$default-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $surface, $on-surface);
166+
$primary-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $primary, $on-primary);
167+
$accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $accent, $on-accent);
168+
$warn-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $error, $on-error);
169+
170+
&.mat-unthemed {
171+
@include mdc-button-filled-theme.theme($default-color-tokens);
172+
}
173+
174+
&.mat-primary {
175+
@include mdc-button-filled-theme.theme($primary-color-tokens);
176+
}
177+
178+
&.mat-accent {
179+
@include mdc-button-filled-theme.theme($accent-color-tokens);
180+
}
181+
182+
&.mat-warn {
183+
@include mdc-button-filled-theme.theme($warn-color-tokens);
184+
}
185+
186+
@include button-theme-private.apply-disabled-style() {
187+
$is-dark: inspection.get-theme-type($theme) == dark;
188+
$disabled-ink-color: rgba($on-surface, if($is-dark, 0.5, 0.38));
189+
$disabled-container-color: rgba($on-surface, 0.12);
190+
191+
@include mdc-button-filled-theme.theme((
192+
disabled-container-color: $disabled-container-color,
193+
disabled-label-text-color: $disabled-ink-color,
194+
container-color: $disabled-container-color,
195+
label-text-color: $disabled-ink-color,
196+
));
197+
}
198+
}
183199
}
184200

185201
@mixin typography($theme) {

src/material/button/button.scss

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
@use '@material/button/button-filled-theme' as mdc-button-filled-theme;
77
@use '@material/button/button-protected-theme' as mdc-button-protected-theme;
88
@use '@material/button/button-outlined-theme' as mdc-button-outlined-theme;
9+
@use '@material/theme/custom-properties' as mdc-custom-properties;
910

1011
@use './button-base';
1112
@use '../core/mdc-helpers/mdc-helpers';
1213
@use '../core/style/private' as style-private;
1314
@use '../core/focus-indicators/private' as focus-indicators-private;
15+
@use '../core/tokens/m2/mdc/button-filled' as tokens-mdc-button-filled;
1416

1517
@include mdc-helpers.disable-mdc-fallback-declarations {
1618
@include mdc-button.static-styles-without-ripple($query: mdc-helpers.$mdc-base-styles-query);
@@ -33,13 +35,6 @@
3335
map.merge(mdc-button-text-theme.$light-theme, $override-keys));
3436
}
3537

36-
.mat-mdc-unelevated-button {
37-
@include mdc-button-filled-theme.theme-styles(
38-
map.merge(map.merge(mdc-button-filled-theme.$light-theme, $override-keys), (
39-
container-color: transparent,
40-
)));
41-
}
42-
4338
.mat-mdc-raised-button {
4439
@include mdc-button-protected-theme.theme-styles(
4540
map.merge(map.merge(mdc-button-protected-theme.$light-theme, $override-keys), (
@@ -53,6 +48,20 @@
5348
}
5449
}
5550

51+
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
52+
// Note that we don't include a feature query, because this mixins declare
53+
// all the "slots" for CSS variables that will be defined in the theme.
54+
.mat-mdc-unelevated-button {
55+
$mdc-button-filled-slots: tokens-mdc-button-filled.get-token-slots();
56+
57+
// Add the slots for MDC text button.
58+
@include mdc-button-filled-theme.theme-styles($mdc-button-filled-slots);
59+
60+
// Add default values for MDC text button tokens that aren't outputted by the theming API.
61+
@include mdc-button-filled-theme.theme(tokens-mdc-button-filled.get-unthemable-tokens());
62+
}
63+
}
64+
5665
.mat-mdc-button,
5766
.mat-mdc-unelevated-button,
5867
.mat-mdc-raised-button,
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
@use '../../token-utils';
2+
@use '../../../mdc-helpers/mdc-helpers';
3+
@use '../../../style/sass-utils';
4+
@use '../../../theming/inspection';
5+
6+
// The prefix used to generate the fully qualified name for tokens in this file.
7+
$prefix: (mdc, button-filled);
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+
container-elevation: 0,
18+
container-height: 36px,
19+
container-shape: 4px,
20+
disabled-container-elevation: 0,
21+
focus-container-elevation: 0,
22+
hover-container-elevation: 0,
23+
keep-touch-target: false,
24+
pressed-container-elevation: 0,
25+
26+
focus-state-layer-opacity: null,
27+
hover-state-layer-opacity: null,
28+
pressed-state-layer-opacity: null,
29+
container-shadow-color: null,
30+
focus-label-text-color: null,
31+
hover-label-text-color: null,
32+
label-text-font: null,
33+
label-text-size: null,
34+
label-text-tracking: null,
35+
label-text-transform: null,
36+
label-text-weight: null,
37+
pressed-label-text-color: null,
38+
with-icon-disabled-icon-color: null,
39+
with-icon-focus-icon-color: null,
40+
with-icon-hover-icon-color: null,
41+
with-icon-icon-color: null,
42+
with-icon-icon-size: null,
43+
with-icon-pressed-icon-color: null
44+
);
45+
}
46+
47+
@function on-color($theme, $palette) {
48+
@if ($palette) {
49+
$is-dark: inspection.get-theme-type($theme) == dark;
50+
@return if(mdc-helpers.variable-safe-contrast-tone($palette, $is-dark) == 'dark', #000, #fff);
51+
}
52+
}
53+
54+
// Tokens that can be configured through Angular Material's color theming API.
55+
@function get-color-tokens($theme, $color: null, $on-color: null) {
56+
$is-dark: inspection.get-theme-type($theme) == dark;
57+
$primary: inspection.get-theme-color($theme, primary);
58+
$surface: inspection.get-theme-color($theme, background, card);
59+
$on-primary: on-color($theme, $primary);
60+
$on-surface: on-color($theme, $surface);
61+
62+
@return (
63+
container-color: if($color, $color, transparent),
64+
disabled-container-color: rgba($on-surface, 0.12),
65+
disabled-label-text-color: rgba($on-surface, if($is-dark, 0.5, 0.38)),
66+
focus-state-layer-color: $on-primary,
67+
hover-state-layer-color: $on-primary,
68+
label-text-color: if($on-color, $on-color, inherit),
69+
pressed-state-layer-color: $on-primary
70+
);
71+
}
72+
73+
// Tokens that can be configured through Angular Material's typography theming API.
74+
@function get-typography-tokens($theme) {
75+
@return ();
76+
}
77+
78+
// Tokens that can be configured through Angular Material's density theming API.
79+
@function get-density-tokens($theme) {
80+
@return ();
81+
}
82+
83+
// Combines the tokens generated by the above functions into a single map with placeholder values.
84+
// This is used to create token slots.
85+
@function get-token-slots() {
86+
@return sass-utils.deep-merge-all(
87+
get-unthemable-tokens(),
88+
get-color-tokens(token-utils.$placeholder-color-config),
89+
get-typography-tokens(token-utils.$placeholder-typography-config),
90+
get-density-tokens(token-utils.$placeholder-density-config)
91+
);
92+
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
@include validate-slots(
105105
$component: 'm2.mdc.switch',
106106
$slots: tokens-mdc-switch.get-token-slots(),
107-
$reference: mdc-switch-theme.$light-theme,
107+
$reference: mdc-switch-theme.$light-theme
108108
);
109109
@include validate-slots(
110110
$component: 'm2.mdc.tab-indicator',
@@ -156,3 +156,8 @@
156156
$slots: tokens-mdc-outlined-text-field.get-token-slots(),
157157
$reference: mdc-outlined-text-field-theme.$light-theme
158158
);
159+
@include validate-slots(
160+
$component: 'm2.mdc.button-filled',
161+
$slots: tokens-mdc-extended-fab.get-token-slots(),
162+
$reference: mdc-extended-fab-theme.$extended-light-theme
163+
);

0 commit comments

Comments
 (0)