Skip to content

Commit 84ef016

Browse files
authored
refactor(material/button-toggle): switch to tokens API (#27509)
Reworks the button toggle component to use the tokens theming API.
1 parent 89c5faf commit 84ef016

File tree

5 files changed

+307
-116
lines changed

5 files changed

+307
-116
lines changed

src/material/button-toggle/_button-toggle-theme.scss

Lines changed: 20 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,41 @@
1-
@use 'sass:map';
2-
@use '../core/style/private';
31
@use '../core/theming/theming';
42
@use '../core/typography/typography';
5-
@use '../core/typography/typography-utils';
6-
@use '../core/density/private/compatibility';
7-
@use './button-toggle-variables';
3+
@use '../core/tokens/m2/mat/legacy-button-toggle' as tokens-mat-legacy-button-toggle;
4+
@use '../core/tokens/m2/mat/standard-button-toggle' as tokens-mat-standard-button-toggle;
5+
@use '../core/tokens/token-utils';
6+
@use '../core/style/sass-utils';
87

98
@mixin color($config-or-theme) {
109
$config: theming.get-color-config($config-or-theme);
11-
$foreground: map.get($config, foreground);
12-
$background: map.get($config, background);
13-
$divider-color: theming.get-color-from-palette($foreground, divider);
14-
$theme-divider-color: map.get($foreground, divider);
1510

16-
// By default the theme usually has an rgba color for the dividers, which can
17-
// stack up with the background of a button toggle. This can cause the border
18-
// of a selected toggle to look different from an deselected one. We use a solid
19-
// color to ensure that the border always stays the same.
20-
$divider-color: if(type-of($theme-divider-color) == color,
21-
theming.private-rgba-to-hex($theme-divider-color, map.get($background, card)),
22-
$theme-divider-color
23-
);
24-
25-
.mat-button-toggle-standalone,
26-
.mat-button-toggle-group {
27-
@include private.private-theme-overridable-elevation(2, $config);
28-
}
29-
30-
.mat-button-toggle-standalone.mat-button-toggle-appearance-standard,
31-
.mat-button-toggle-group-appearance-standard {
32-
&:not([class*='mat-elevation-z']) {
33-
box-shadow: none;
34-
}
35-
}
36-
37-
.mat-button-toggle {
38-
color: theming.get-color-from-palette($foreground, hint-text);
39-
40-
.mat-button-toggle-focus-overlay {
41-
background-color: theming.get-color-from-palette($background, focused-button);
42-
}
43-
}
44-
45-
.mat-button-toggle-appearance-standard {
46-
color: theming.get-color-from-palette($foreground, text);
47-
background: theming.get-color-from-palette($background, card);
48-
49-
.mat-button-toggle-focus-overlay {
50-
background-color: theming.get-color-from-palette($background, focused-button, 1);
51-
}
52-
}
53-
54-
.mat-button-toggle-group-appearance-standard .mat-button-toggle + .mat-button-toggle {
55-
border-left: solid 1px $divider-color;
56-
}
57-
58-
[dir='rtl'] .mat-button-toggle-group-appearance-standard .mat-button-toggle + .mat-button-toggle {
59-
border-left: none;
60-
border-right: solid 1px $divider-color;
61-
}
62-
63-
.mat-button-toggle-group-appearance-standard.mat-button-toggle-vertical {
64-
.mat-button-toggle + .mat-button-toggle {
65-
border-left: none;
66-
border-right: none;
67-
border-top: solid 1px $divider-color;
68-
}
69-
}
70-
71-
.mat-button-toggle-checked {
72-
background-color: theming.get-color-from-palette($background, selected-button);
73-
color: theming.get-color-from-palette($foreground, secondary-text);
74-
75-
&.mat-button-toggle-appearance-standard {
76-
color: theming.get-color-from-palette($foreground, text);
77-
}
78-
}
79-
80-
.mat-button-toggle-disabled {
81-
color: theming.get-color-from-palette($foreground, disabled-button);
82-
background-color: theming.get-color-from-palette($background, disabled-button-toggle);
83-
84-
&.mat-button-toggle-appearance-standard {
85-
background: theming.get-color-from-palette($background, card);
86-
}
87-
88-
&.mat-button-toggle-checked {
89-
background-color: theming.get-color-from-palette($background, selected-disabled-button);
90-
}
91-
}
92-
93-
.mat-button-toggle-standalone.mat-button-toggle-appearance-standard,
94-
.mat-button-toggle-group-appearance-standard {
95-
border: solid 1px $divider-color;
11+
@include sass-utils.current-selector-or-root() {
12+
@include token-utils.create-token-values(tokens-mat-legacy-button-toggle.$prefix,
13+
tokens-mat-legacy-button-toggle.get-color-tokens($config));
14+
@include token-utils.create-token-values(tokens-mat-standard-button-toggle.$prefix,
15+
tokens-mat-standard-button-toggle.get-color-tokens($config));
9616
}
9717
}
9818

9919
@mixin typography($config-or-theme) {
10020
$config: typography.private-typography-to-2014-config(
10121
theming.get-typography-config($config-or-theme));
102-
.mat-button-toggle {
103-
font-family: typography-utils.font-family($config);
22+
23+
@include sass-utils.current-selector-or-root() {
24+
@include token-utils.create-token-values(tokens-mat-legacy-button-toggle.$prefix,
25+
tokens-mat-legacy-button-toggle.get-typography-tokens($config));
26+
@include token-utils.create-token-values(tokens-mat-standard-button-toggle.$prefix,
27+
tokens-mat-standard-button-toggle.get-typography-tokens($config));
10428
}
10529
}
10630

10731
@mixin density($config-or-theme) {
10832
$density-scale: theming.get-density-config($config-or-theme);
109-
$standard-height: compatibility.private-density-prop-value(
110-
button-toggle-variables.$standard-density-config, $density-scale, height);
11133

112-
@include compatibility.private-density-legacy-compatibility() {
113-
.mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
114-
line-height: $standard-height;
115-
}
34+
@include sass-utils.current-selector-or-root() {
35+
@include token-utils.create-token-values(tokens-mat-legacy-button-toggle.$prefix,
36+
tokens-mat-legacy-button-toggle.get-density-tokens($density-scale));
37+
@include token-utils.create-token-values(tokens-mat-standard-button-toggle.$prefix,
38+
tokens-mat-standard-button-toggle.get-density-tokens($density-scale));
11639
}
11740
}
11841

src/material/button-toggle/_button-toggle-variables.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// TODO(crisbeto): this file isn't used anymore and should be removed.
2+
13
$standard-height: 48px !default;
24
// Minimum height for highest density can vary based on the content that developers
35
// project into button-toggle's. We use a minimum of `24px` though because commonly

src/material/button-toggle/button-toggle.scss

Lines changed: 135 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,71 @@
22

33
@use '../core/style/vendor-prefixes';
44
@use '../core/style/layout-common';
5+
@use '../core/style/elevation';
6+
@use '../core/tokens/token-utils';
7+
@use '../core/tokens/m2/mat/legacy-button-toggle' as tokens-mat-legacy-button-toggle;
8+
@use '../core/tokens/m2/mat/standard-button-toggle' as tokens-mat-standard-button-toggle;
59

610
$standard-padding: 0 12px !default;
7-
$standard-border-radius: 4px !default;
8-
911
$legacy-padding: 0 16px !default;
12+
13+
// TODO(crisbeto): these variables aren't used anymore and should be removed.
1014
$legacy-height: 36px !default;
15+
$standard-border-radius: 4px !default;
1116
$legacy-border-radius: 2px !default;
1217

18+
$_legacy-tokens: (
19+
tokens-mat-legacy-button-toggle.$prefix,
20+
tokens-mat-legacy-button-toggle.get-token-slots()
21+
);
22+
23+
$_standard-tokens: (
24+
tokens-mat-standard-button-toggle.$prefix,
25+
tokens-mat-standard-button-toggle.get-token-slots()
26+
);
27+
1328
.mat-button-toggle-standalone,
1429
.mat-button-toggle-group {
30+
@include token-utils.create-token-values(
31+
tokens-mat-legacy-button-toggle.$prefix,
32+
tokens-mat-legacy-button-toggle.get-unthemable-tokens()
33+
);
34+
35+
@include elevation.overridable-elevation(2);
1536
position: relative;
1637
display: inline-flex;
1738
flex-direction: row;
1839
white-space: nowrap;
1940
overflow: hidden;
20-
border-radius: $legacy-border-radius;
2141
-webkit-tap-highlight-color: transparent;
2242

2343
// Fixes the ripples not being clipped to the border radius on Safari.
2444
transform: translateZ(0);
2545

46+
@include token-utils.use-tokens($_legacy-tokens...) {
47+
@include token-utils.create-token-slot(border-radius, shape);
48+
}
49+
2650
@include cdk.high-contrast(active, off) {
2751
outline: solid 1px;
2852
}
2953
}
3054

3155
.mat-button-toggle-standalone.mat-button-toggle-appearance-standard,
3256
.mat-button-toggle-group-appearance-standard {
33-
border-radius: $standard-border-radius;
57+
@include token-utils.create-token-values(
58+
tokens-mat-standard-button-toggle.$prefix,
59+
tokens-mat-standard-button-toggle.get-unthemable-tokens()
60+
);
61+
62+
@include token-utils.use-tokens($_standard-tokens...) {
63+
@include token-utils.create-token-slot(border-radius, shape);
64+
border: solid 1px var(#{token-utils.get-token-variable(divider-color)});
65+
}
66+
67+
&:not([class*='mat-elevation-z']) {
68+
box-shadow: none;
69+
}
3470

3571
@include cdk.high-contrast(active, off) {
3672
outline: 0;
@@ -51,30 +87,99 @@ $legacy-border-radius: 2px !default;
5187
white-space: nowrap;
5288
position: relative;
5389

90+
@include token-utils.use-tokens($_legacy-tokens...) {
91+
@include token-utils.create-token-slot(color, text-color);
92+
@include token-utils.create-token-slot(font-family, text-font);
93+
94+
&.cdk-keyboard-focused .mat-button-toggle-focus-overlay {
95+
@include token-utils.create-token-slot(opacity, focus-state-layer-opacity);
96+
}
97+
}
98+
5499
// Fixes SVG icons that get thrown off because of the `vertical-align` on the parent.
55100
.mat-icon svg {
56101
vertical-align: top;
57102
}
103+
}
58104

59-
&.cdk-keyboard-focused {
60-
.mat-button-toggle-focus-overlay {
61-
opacity: 1;
105+
.mat-button-toggle-checked {
106+
@include token-utils.use-tokens($_legacy-tokens...) {
107+
@include token-utils.create-token-slot(color, selected-state-text-color);
108+
@include token-utils.create-token-slot(background-color, selected-state-background-color);
109+
}
110+
}
111+
112+
.mat-button-toggle-disabled {
113+
@include token-utils.use-tokens($_legacy-tokens...) {
114+
@include token-utils.create-token-slot(color, disabled-state-text-color);
115+
@include token-utils.create-token-slot(background-color, disabled-state-background-color);
116+
117+
&.mat-button-toggle-checked {
118+
@include token-utils.create-token-slot(background-color,
119+
disabled-selected-state-background-color);
62120
}
63121
}
64122
}
65123

66124
.mat-button-toggle-appearance-standard {
67-
&:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay {
68-
opacity: 0.04;
69-
}
125+
@include token-utils.create-token-values(
126+
tokens-mat-standard-button-toggle.$prefix,
127+
tokens-mat-standard-button-toggle.get-unthemable-tokens()
128+
);
129+
130+
@include token-utils.use-tokens($_standard-tokens...) {
131+
$divider-color: var(#{token-utils.get-token-variable(divider-color)});
132+
@include token-utils.create-token-slot(color, text-color);
133+
@include token-utils.create-token-slot(background-color, background-color);
134+
@include token-utils.create-token-slot(font-family, text-font);
70135

71-
// Similar to components like the checkbox, slide-toggle and radio, we cannot show the focus
72-
// overlay for `.cdk-program-focused` because mouse clicks on the <label> element would be always
73-
// treated as programmatic focus. Note that it needs the extra `:not` in order to have more
74-
// specificity than the `:hover` above.
75-
// TODO(paul): support `program` as well. See https://github.com/angular/components/issues/9889
76-
&.cdk-keyboard-focused:not(.mat-button-toggle-disabled) .mat-button-toggle-focus-overlay {
77-
opacity: 0.12;
136+
.mat-button-toggle-group-appearance-standard & + & {
137+
border-left: solid 1px $divider-color;
138+
}
139+
140+
[dir='rtl'] .mat-button-toggle-group-appearance-standard & + & {
141+
border-left: none;
142+
border-right: solid 1px $divider-color;
143+
}
144+
145+
.mat-button-toggle-group-appearance-standard.mat-button-toggle-vertical & + & {
146+
border-left: none;
147+
border-right: none;
148+
border-top: solid 1px $divider-color;
149+
}
150+
151+
&.mat-button-toggle-checked {
152+
@include token-utils.create-token-slot(color, selected-state-text-color);
153+
@include token-utils.create-token-slot(background-color, selected-state-background-color);
154+
}
155+
156+
&.mat-button-toggle-disabled {
157+
@include token-utils.create-token-slot(color, disabled-state-text-color);
158+
@include token-utils.create-token-slot(background-color, disabled-state-background-color);
159+
160+
&.mat-button-toggle-checked {
161+
@include token-utils.create-token-slot(color, disabled-selected-state-text-color);
162+
@include token-utils.create-token-slot(background-color,
163+
disabled-selected-state-background-color);
164+
}
165+
}
166+
167+
.mat-button-toggle-focus-overlay {
168+
@include token-utils.create-token-slot(background-color, state-layer-color);
169+
}
170+
171+
&:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay {
172+
@include token-utils.create-token-slot(opacity, hover-state-layer-opacity);
173+
}
174+
175+
// Similar to components like the checkbox, slide-toggle and radio, we cannot show the focus
176+
// overlay for `.cdk-program-focused` because mouse clicks on the <label> element would be
177+
// always treated as programmatic focus. Note that it needs the extra `:not` in order to have
178+
// more specificity than the `:hover` above.
179+
// TODO(paul): support `program` as well. See https://github.com/angular/components/issues/9889
180+
&.cdk-keyboard-focused:not(.mat-button-toggle-disabled) .mat-button-toggle-focus-overlay {
181+
@include token-utils.create-token-slot(opacity, focus-state-layer-opacity);
182+
}
78183
}
79184

80185
// On touch devices the hover state will linger on the element after the user has tapped.
@@ -91,14 +196,21 @@ $legacy-border-radius: 2px !default;
91196
.mat-button-toggle-label-content {
92197
@include vendor-prefixes.user-select(none);
93198
display: inline-block;
94-
line-height: $legacy-height;
95199
padding: $legacy-padding;
96200

201+
@include token-utils.use-tokens($_legacy-tokens...) {
202+
@include token-utils.create-token-slot(line-height, height);
203+
}
204+
97205
// Prevents IE from shifting the content on click.
98206
position: relative;
99207

100208
.mat-button-toggle-appearance-standard & {
101209
padding: $standard-padding;
210+
211+
@include token-utils.use-tokens($_standard-tokens...) {
212+
@include token-utils.create-token-slot(line-height, height);
213+
}
102214
}
103215
}
104216

@@ -114,6 +226,10 @@ $legacy-border-radius: 2px !default;
114226
// Disable pointer events to prevent it from hijacking user events.
115227
pointer-events: none;
116228
opacity: 0;
229+
230+
@include token-utils.use-tokens($_legacy-tokens...) {
231+
@include token-utils.create-token-slot(background-color, state-layer-color);
232+
}
117233
}
118234

119235
@include cdk.high-contrast(active, off) {
@@ -122,7 +238,7 @@ $legacy-border-radius: 2px !default;
122238
// It uses a border, because the browser will render it using a brighter color.
123239
.mat-button-toggle-checked {
124240
.mat-button-toggle-focus-overlay {
125-
border-bottom: solid $legacy-height;
241+
border-bottom: solid 500px;
126242
opacity: 0.5;
127243
height: 0;
128244
}

0 commit comments

Comments
 (0)