Skip to content

Commit 4e309b2

Browse files
committed
refactor(material-experimental/mdc-button): switch to new theming API
Switches the MDC-based buttons to the new token-based theming API.
1 parent 0f47b7a commit 4e309b2

File tree

11 files changed

+386
-184
lines changed

11 files changed

+386
-184
lines changed

src/material-experimental/mdc-button/_button-base.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
// pointer events.
1010
@mixin mat-private-button-interactive() {
1111
.mdc-button__ripple::before, .mdc-button__ripple::after,
12-
.mdc-fab__ripple::before, .mdc-fab__ripple::after {
12+
.mdc-fab__ripple::before, .mdc-fab__ripple::after,
13+
.mdc-icon-button__ripple::before, .mdc-icon-button__ripple::after {
1314
content: '';
1415
pointer-events: none;
1516
position: absolute;
@@ -23,7 +24,7 @@
2324
}
2425

2526
// The ripple container should match the bounds of the entire button.
26-
.mat-mdc-button-ripple, .mdc-button__ripple, .mdc-fab__ripple {
27+
.mat-mdc-button-ripple, .mdc-button__ripple, .mdc-fab__ripple, .mdc-icon-button__ripple {
2728
@include layout-common.fill;
2829

2930
// Disable pointer events for the ripple container and state overlay because the container
@@ -59,6 +60,7 @@
5960
&[disabled] {
6061
cursor: default;
6162
pointer-events: none;
63+
@content;
6264
}
6365
}
6466

src/material-experimental/mdc-button/_button-theme-private.scss

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
@use '@material/theme/theme-color' as mdc-theme-color;
2-
@use '@material/theme/theme' as mdc-theme;
1+
@use 'sass:map';
2+
@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
33
@use '../../material/core/ripple/ripple-theme';
44

5-
// Selector for the element that has a background color and opacity applied to its ::before and
6-
// ::after for state interactions (hover, active, focus). Their API calls this their
7-
// "ripple target", but we do not use it as our ripple, just state color.
8-
$button-state-target: '.mdc-button__ripple';
9-
$fab-state-target: '.mdc-fab__ripple';
10-
115
// The MDC button's ripple ink color is based on the theme color, not on the foreground base
126
// which is what the ripple mixin uses. This creates a new theme that sets the color to the
137
// foreground base to appropriately color the ink.
14-
@mixin ripple-ink-color($mdc-color) {
8+
@mixin ripple-ink-color($color) {
159
@include ripple-theme.color((
1610
foreground: (
17-
base: mdc-theme-color.prop-value($mdc-color)
11+
base: $color
1812
),
1913
));
2014
}
2115

22-
// Applies the disabled theme color to the text color.
23-
@mixin apply-disabled-color() {
24-
@include mdc-theme.prop(color,
25-
mdc-theme-color.ink-color-for-fill_(disabled, mdc-theme-color.$background));
16+
// MDC's ripple opacity depends on whether the theme is dark or light.
17+
// This function adds the correct mapping to the theme tokens.
18+
@function add-ripple-opacities($is-dark-theme, $tokens: ()) {
19+
$opacities: if($is-dark-theme,
20+
mdc-ripple-theme.$light-ink-opacities, mdc-ripple-theme.$dark-ink-opacities);
21+
@return map.merge($tokens, (
22+
focus-state-layer-opacity: map.get($opacities, focus),
23+
hover-state-layer-opacity: map.get($opacities, hover),
24+
pressed-state-layer-opacity: map.get($opacities, press),
25+
));
2626
}
2727

2828
// Wraps the content style in a selector for the disabled state.
@@ -37,14 +37,6 @@ $fab-state-target: '.mdc-fab__ripple';
3737
}
3838
}
3939

40-
// Applies the disabled theme background color for raised buttons. Value is taken from
41-
// mixin `mdc-button--filled`.
42-
// TODO(andrewseguin): Discuss with the MDC team about providing a variable for the 0.12 value
43-
// or otherwise have a mixin we can call to apply this style for both button and anchors.
44-
@mixin apply-disabled-background() {
45-
@include mdc-theme.prop(background-color, rgba(mdc-theme-color.prop-value(on-surface), 0.12));
46-
}
47-
4840
// Hides the touch target on lower densities.
4941
@mixin touch-target-density($scale) {
5042
@if ($scale == -2 or $scale == 'minimum') {

src/material-experimental/mdc-button/_button-theme.scss

Lines changed: 154 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1,222 @@
1+
@use 'sass:map';
12
@use '@material/button/button' as mdc-button;
23
@use '@material/button/button-theme' as mdc-button-theme;
3-
@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
4+
@use '@material/button/button-text-theme' as mdc-button-text-theme;
5+
@use '@material/button/button-filled-theme' as mdc-button-filled-theme;
6+
@use '@material/button/button-protected-theme' as mdc-button-protected-theme;
7+
@use '@material/button/button-outlined-theme' as mdc-button-outlined-theme;
48
@use '@material/theme/theme-color' as mdc-theme-color;
5-
@use '@material/theme/theme' as mdc-theme;
6-
@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
7-
@use '../../material/core/ripple/ripple-theme';
89
@use '../../material/core/typography/typography';
910
@use '../mdc-helpers/mdc-helpers';
1011
@use '../../material/core/theming/theming';
1112
@use './button-theme-private';
1213

14+
@mixin _button-variant($color) {
15+
@include mdc-button-text-theme.theme((
16+
focus-state-layer-color: $color,
17+
hover-state-layer-color: $color,
18+
label-text-color: $color,
19+
pressed-state-layer-color: $color,
20+
));
21+
}
22+
23+
@mixin _unelevated-button-variant($foreground, $background) {
24+
@include mdc-button-filled-theme.theme((
25+
container-color: $background,
26+
focus-state-layer-color: $foreground,
27+
hover-state-layer-color: $foreground,
28+
label-text-color: $foreground,
29+
pressed-state-layer-color: $foreground,
30+
));
31+
}
32+
33+
@mixin _raised-button-variant($foreground, $background) {
34+
@include mdc-button-protected-theme.theme((
35+
container-color: $background,
36+
focus-state-layer-color: $foreground,
37+
hover-state-layer-color: $foreground,
38+
label-text-color: $foreground,
39+
pressed-state-layer-color: $foreground,
40+
));
41+
}
42+
43+
@mixin _outlined-button-variant($color) {
44+
@include mdc-button-outlined-theme.theme((
45+
focus-state-layer-color: $color,
46+
hover-state-layer-color: $color,
47+
label-text-color: $color,
48+
outline-color: $color,
49+
pressed-state-layer-color: $color,
50+
));
51+
}
52+
1353
@mixin color($config-or-theme) {
1454
$config: theming.get-color-config($config-or-theme);
1555
@include mdc-helpers.mat-using-mdc-theme($config) {
16-
// Add state interactions for hover, focus, press, active. Colors are changed based on
17-
// the mixin mdc-states-base-color
18-
.mat-mdc-button, .mat-mdc-raised-button, .mat-mdc-unelevated-button, .mat-mdc-outlined-button {
19-
@include mdc-ripple-theme.states(
20-
$query: mdc-helpers.$mat-theme-styles-query,
21-
$ripple-target: button-theme-private.$button-state-target);
22-
}
56+
$is-dark: map.get($config, is-dark);
57+
$on-surface: mdc-theme-color.prop-value(on-surface);
58+
$surface: mdc-theme-color.prop-value(surface);
59+
$disabled-ink-color: rgba($on-surface, if($is-dark, 0.5, 0.38));
60+
$disabled-container-color: rgba($on-surface, 0.12);
61+
$primary: mdc-theme-color.prop-value(primary);
62+
$on-primary: mdc-theme-color.prop-value(on-primary);
63+
$secondary: mdc-theme-color.prop-value(secondary);
64+
$on-secondary: mdc-theme-color.prop-value(on-secondary);
65+
$error: mdc-theme-color.prop-value(error);
66+
$on-error: mdc-theme-color.prop-value(on-error);
67+
68+
.mat-mdc-button {
69+
@include mdc-button-text-theme.theme(button-theme-private.add-ripple-opacities($is-dark));
2370

24-
.mat-mdc-button, .mat-mdc-outlined-button {
2571
&.mat-unthemed {
26-
@include mdc-button-theme.ink-color(mdc-theme-color.$on-surface,
27-
$query: mdc-helpers.$mat-theme-styles-query);
72+
@include _button-variant($on-surface);
2873
}
2974

3075
&.mat-primary {
31-
@include mdc-button-theme.ink-color(primary, $query: mdc-helpers.$mat-theme-styles-query);
32-
@include mdc-ripple-theme.states-base-color(primary,
33-
$query: mdc-helpers.$mat-theme-styles-query,
34-
$ripple-target: button-theme-private.$button-state-target);
35-
@include button-theme-private.ripple-ink-color(primary);
76+
@include _button-variant($primary);
3677
}
3778

3879
&.mat-accent {
39-
@include mdc-button-theme.ink-color(secondary, $query: mdc-helpers.$mat-theme-styles-query);
40-
@include mdc-ripple-theme.states-base-color(secondary,
41-
$query: mdc-helpers.$mat-theme-styles-query,
42-
$ripple-target: button-theme-private.$button-state-target);
43-
@include button-theme-private.ripple-ink-color(secondary);
80+
@include _button-variant($secondary);
4481
}
4582

4683
&.mat-warn {
47-
@include mdc-button-theme.ink-color(error, $query: mdc-helpers.$mat-theme-styles-query);
48-
@include mdc-ripple-theme.states-base-color(error,
49-
$query: mdc-helpers.$mat-theme-styles-query,
50-
$ripple-target: button-theme-private.$button-state-target);
51-
@include button-theme-private.ripple-ink-color(error);
84+
@include _button-variant($error);
85+
}
86+
87+
@include button-theme-private.apply-disabled-style() {
88+
@include mdc-button-text-theme.theme((
89+
// We need to pass both the disabled and enabled values, because the enabled
90+
// ones apply to anchors while the disabled ones are for buttons.
91+
disabled-label-text-color: $disabled-ink-color,
92+
label-text-color: $disabled-ink-color
93+
));
5294
}
5395
}
5496

55-
.mat-mdc-raised-button,
5697
.mat-mdc-unelevated-button {
98+
@include mdc-button-filled-theme.theme(button-theme-private.add-ripple-opacities($is-dark));
99+
57100
&.mat-unthemed {
58-
@include mdc-button-theme.container-fill-color(mdc-theme-color.$surface,
59-
$query: mdc-helpers.$mat-theme-styles-query);
60-
@include mdc-button-theme.ink-color(mdc-theme-color.$on-surface,
61-
$query: mdc-helpers.$mat-theme-styles-query);
62-
@include mdc-ripple-theme.states-base-color(mdc-theme-color.$on-surface,
63-
$query: mdc-helpers.$mat-theme-styles-query,
64-
$ripple-target: button-theme-private.$button-state-target);
101+
@include _unelevated-button-variant($on-surface, $surface);
65102
}
66103

67104
&.mat-primary {
68-
@include mdc-button-theme.container-fill-color(primary,
69-
$query: mdc-helpers.$mat-theme-styles-query);
70-
@include mdc-button-theme.ink-color(on-primary,
71-
$query: mdc-helpers.$mat-theme-styles-query);
72-
@include mdc-ripple-theme.states-base-color(on-primary,
73-
$query: mdc-helpers.$mat-theme-styles-query,
74-
$ripple-target: button-theme-private.$button-state-target);
75-
@include button-theme-private.ripple-ink-color(on-primary);
105+
@include _unelevated-button-variant($on-primary, $primary);
76106
}
77107

78108
&.mat-accent {
79-
@include mdc-button-theme.container-fill-color(secondary,
80-
$query: mdc-helpers.$mat-theme-styles-query);
81-
@include mdc-button-theme.ink-color(on-secondary,
82-
$query: mdc-helpers.$mat-theme-styles-query);
83-
@include mdc-ripple-theme.states-base-color(on-secondary,
84-
$query: mdc-helpers.$mat-theme-styles-query,
85-
$ripple-target: button-theme-private.$button-state-target);
86-
@include button-theme-private.ripple-ink-color(on-secondary);
109+
@include _unelevated-button-variant($on-secondary, $secondary);
87110
}
88111

89112
&.mat-warn {
90-
@include mdc-button-theme.container-fill-color(error,
91-
$query: mdc-helpers.$mat-theme-styles-query);
92-
@include mdc-button-theme.ink-color(on-error, $query: mdc-helpers.$mat-theme-styles-query);
93-
@include mdc-ripple-theme.states-base-color(on-error,
94-
$query: mdc-helpers.$mat-theme-styles-query,
95-
$ripple-target: button-theme-private.$button-state-target);
96-
@include button-theme-private.ripple-ink-color(on-error);
113+
@include _unelevated-button-variant($on-error, $error);
97114
}
98115

99116
@include button-theme-private.apply-disabled-style() {
100-
@include button-theme-private.apply-disabled-background();
117+
@include mdc-button-filled-theme.theme((
118+
// We need to pass both the disabled and enabled values, because the enabled
119+
// ones apply to anchors while the disabled ones are for buttons.
120+
disabled-container-color: $disabled-container-color,
121+
disabled-label-text-color: $disabled-ink-color,
122+
container-color: $disabled-container-color,
123+
label-text-color: $disabled-ink-color,
124+
));
101125
}
102126
}
103127

104-
.mat-mdc-outlined-button {
128+
.mat-mdc-raised-button {
129+
@include mdc-button-protected-theme.theme(
130+
button-theme-private.add-ripple-opacities($is-dark));
131+
105132
&.mat-unthemed {
106-
@include mdc-button-theme.outline-color(mdc-theme-color.$on-surface,
107-
$query: mdc-helpers.$mat-theme-styles-query);
133+
@include _raised-button-variant($on-surface, $surface);
108134
}
109135

110136
&.mat-primary {
111-
@include mdc-button-theme.outline-color(primary,
112-
$query: mdc-helpers.$mat-theme-styles-query);
137+
@include _raised-button-variant($on-primary, $primary);
113138
}
114139

115140
&.mat-accent {
116-
@include mdc-button-theme.outline-color(secondary,
117-
$query: mdc-helpers.$mat-theme-styles-query);
141+
@include _raised-button-variant($on-secondary, $secondary);
118142
}
119143

120144
&.mat-warn {
121-
@include mdc-button-theme.outline-color(error,
122-
$query: mdc-helpers.$mat-theme-styles-query);
145+
@include _raised-button-variant($on-error, $error);
123146
}
124147

125148
@include button-theme-private.apply-disabled-style() {
126-
@include mdc-theme.prop(border-color,
127-
mdc-theme-color.ink-color-for-fill_(disabled, mdc-theme-color.$background));
149+
@include mdc-button-protected-theme.theme((
150+
// We need to pass both the disabled and enabled values, because the enabled
151+
// ones apply to anchors while the disabled ones are for buttons.
152+
disabled-container-color: $disabled-container-color,
153+
disabled-label-text-color: $disabled-ink-color,
154+
container-color: $disabled-container-color,
155+
label-text-color: $disabled-ink-color,
156+
container-elevation: 0,
157+
));
128158
}
129159
}
130160

131-
.mat-mdc-raised-button {
161+
.mat-mdc-outlined-button {
162+
@include mdc-button-outlined-theme.theme(button-theme-private.add-ripple-opacities($is-dark));
163+
164+
&.mat-unthemed {
165+
@include _outlined-button-variant($on-surface);
166+
}
167+
168+
&.mat-primary {
169+
@include _outlined-button-variant($primary);
170+
}
171+
172+
&.mat-accent {
173+
@include _outlined-button-variant($secondary);
174+
}
175+
176+
&.mat-warn {
177+
@include _outlined-button-variant($error);
178+
}
179+
132180
@include button-theme-private.apply-disabled-style() {
133-
@include mdc-elevation-theme.elevation(0, $query: mdc-helpers.$mat-theme-styles-query);
181+
@include mdc-button-outlined-theme.theme((
182+
// We need to pass both the disabled and enabled values, because the enabled
183+
// ones apply to anchors while the disabled ones are for buttons.
184+
label-text-color: $disabled-ink-color,
185+
outline-color: $disabled-ink-color,
186+
disabled-label-text-color: $disabled-ink-color,
187+
disabled-outline-color: $disabled-ink-color,
188+
));
134189
}
135190
}
136191

137-
.mat-mdc-button, .mat-mdc-raised-button, .mat-mdc-unelevated-button, .mat-mdc-outlined-button {
138-
@include button-theme-private.apply-disabled-style() {
139-
@include button-theme-private.apply-disabled-color();
192+
// Ripple colors
193+
.mat-mdc-button, .mat-mdc-outlined-button {
194+
&.mat-primary {
195+
@include button-theme-private.ripple-ink-color($primary);
196+
}
197+
198+
&.mat-accent {
199+
@include button-theme-private.ripple-ink-color($secondary);
200+
}
201+
202+
&.mat-warn {
203+
@include button-theme-private.ripple-ink-color($error);
140204
}
141205
}
142206

143-
@include mdc-button.without-ripple($query: mdc-helpers.$mat-theme-styles-query);
207+
.mat-mdc-raised-button, .mat-mdc-unelevated-button {
208+
&.mat-primary {
209+
@include button-theme-private.ripple-ink-color($on-primary);
210+
}
211+
212+
&.mat-accent {
213+
@include button-theme-private.ripple-ink-color($on-secondary);
214+
}
215+
216+
&.mat-warn {
217+
@include button-theme-private.ripple-ink-color($on-error);
218+
}
219+
}
144220
}
145221
}
146222

0 commit comments

Comments
 (0)