Skip to content

Commit d799c04

Browse files
authored
fix(material/slide-toggle): fix m3 slide-toggle handle (#28503)
* fix(material/slide-toggle): boilerplate for m3 custom tokens * create a custom-tokens function * set up theme mixins to create custom token values * create an m2 mat- tokens file * added a new namespace in _m3-tokens.scss * appended the new tokens to m2-tokens-from-theme * fix(material/slide-toggle): fix m3 width, height, and margin
1 parent f20e4ed commit d799c04

File tree

6 files changed

+161
-7
lines changed

6 files changed

+161
-7
lines changed

src/material-experimental/theming/_custom-tokens.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,25 @@
10941094
));
10951095
}
10961096

1097+
/// Generates custom tokens for the mat-slide-toggle.
1098+
/// @param {Map} $systems The MDC system tokens
1099+
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
1100+
/// @return {Map} A set of custom tokens for the mat-slide-toggle
1101+
@function switch($systems, $exclude-hardcoded) {
1102+
@return ((
1103+
unselected-handle-size: 16px,
1104+
selected-handle-size: 24px,
1105+
with-icon-handle-size: 24px,
1106+
pressed-handle-size: 28px,
1107+
selected-handle-horizontal-margin: 0 24px,
1108+
selected-with-icon-handle-horizontal-margin: 0 24px,
1109+
selected-pressed-handle-horizontal-margin: 0 22px,
1110+
unselected-handle-horizontal-margin: 0 8px,
1111+
unselected-with-icon-handle-horizontal-margin: 0 4px,
1112+
unselected-pressed-handle-horizontal-margin: 0 2px,
1113+
), ());
1114+
}
1115+
10971116
/// Generates custom tokens for the mat-snack-bar.
10981117
/// @param {Map} $systems The MDC system tokens
10991118
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values

src/material-experimental/theming/_m3-tokens.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,11 @@
904904
custom-tokens.stepper($systems, $exclude-hardcoded),
905905
$token-slots
906906
),
907+
_namespace-tokens(
908+
(mat, switch),
909+
custom-tokens.switch($systems, $exclude-hardcoded),
910+
$token-slots
911+
),
907912
_namespace-tokens(
908913
(mat, tab-header),
909914
custom-tokens.tab-header($systems, $exclude-hardcoded),

src/material/core/tokens/m2/_index.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
@use './mat/select' as tokens-mat-select;
3333
@use './mat/sidenav' as tokens-mat-sidenav;
3434
@use './mat/slider' as tokens-mat-slider;
35+
@use './mat/switch' as tokens-mat-switch;
3536
@use './mat/snack-bar' as tokens-mat-snack-bar;
3637
@use './mat/sort' as tokens-mat-sort;
3738
@use './mat/standard-button-toggle' as tokens-mat-button-toggle;
@@ -142,6 +143,7 @@
142143
_get-tokens-for-module($theme, tokens-mat-select),
143144
_get-tokens-for-module($theme, tokens-mat-sidenav),
144145
_get-tokens-for-module($theme, tokens-mat-slider),
146+
_get-tokens-for-module($theme, tokens-mat-switch),
145147
_get-tokens-for-module($theme, tokens-mat-snack-bar),
146148
_get-tokens-for-module($theme, tokens-mat-sort),
147149
_get-tokens-for-module($theme, tokens-mat-stepper),
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
@use '../../token-utils';
2+
@use '../../../style/sass-utils';
3+
4+
// The prefix used to generate the fully qualified name for tokens in this file.
5+
$prefix: (mat, switch);
6+
7+
// Tokens that can't be configured through Angular Material's current theming API,
8+
// but may be in a future version of the theming API.
9+
@function get-unthemable-tokens() {
10+
@return (
11+
unselected-handle-size: 20px,
12+
selected-handle-size: 20px,
13+
pressed-handle-size: 20px,
14+
with-icon-handle-size: 20px,
15+
16+
selected-handle-horizontal-margin: 0,
17+
selected-with-icon-handle-horizontal-margin: 0,
18+
selected-pressed-handle-horizontal-margin: 0,
19+
unselected-handle-horizontal-margin: 0,
20+
unselected-with-icon-handle-horizontal-margin: 0,
21+
unselected-pressed-handle-horizontal-margin: 0,
22+
);
23+
}
24+
25+
// Tokens that can be configured through Angular Material's color theming API.
26+
@function get-color-tokens($theme) {
27+
@return ();
28+
}
29+
30+
// Tokens that can be configured through Angular Material's typography theming API.
31+
@function get-typography-tokens($theme) {
32+
@return ();
33+
}
34+
35+
// Tokens that can be configured through Angular Material's density theming API.
36+
@function get-density-tokens($theme) {
37+
@return ();
38+
}
39+
40+
// Combines the tokens generated by the above functions into a single map with placeholder values.
41+
// This is used to create token slots.
42+
@function get-token-slots() {
43+
@return sass-utils.deep-merge-all(
44+
get-unthemable-tokens(),
45+
get-color-tokens(token-utils.$placeholder-color-config),
46+
get-typography-tokens(token-utils.$placeholder-typography-config),
47+
get-density-tokens(token-utils.$placeholder-density-config)
48+
);
49+
}

src/material/slide-toggle/_slide-toggle-theme.scss

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@use '../core/tokens/token-utils';
77
@use '../core/typography/typography';
88
@use '../core/tokens/m2/mdc/form-field' as tokens-mdc-form-field;
9+
@use '../core/tokens/m2/mat/switch' as tokens-mat-switch;
910
@use '../core/tokens/m2/mdc/switch' as tokens-mdc-switch;
1011

1112
/// Outputs base theme styles (styles not dependent on the color, typography, or density settings)
@@ -17,7 +18,10 @@
1718
}
1819
@else {
1920
@include sass-utils.current-selector-or-root() {
20-
@include mdc-switch-theme.theme(tokens-mdc-switch.get-unthemable-tokens());
21+
$mat-tokens: tokens-mat-switch.get-unthemable-tokens();
22+
$mdc-tokens: tokens-mdc-switch.get-unthemable-tokens();
23+
@include mdc-switch-theme.theme($mdc-tokens);
24+
@include token-utils.create-token-values(tokens-mat-switch.$prefix, $mat-tokens);
2125
}
2226
}
2327
}
@@ -33,11 +37,13 @@
3337
}
3438
@else {
3539
$is-dark: inspection.get-theme-type($theme) == dark;
36-
$mdc-switch-color-tokens: tokens-mdc-switch.get-color-tokens($theme);
40+
$mat-tokens: tokens-mat-switch.get-color-tokens($theme);
41+
$mdc-tokens: tokens-mdc-switch.get-color-tokens($theme);
3742

3843
// Add values for MDC slide toggles tokens
3944
@include sass-utils.current-selector-or-root() {
40-
@include mdc-switch-theme.theme($mdc-switch-color-tokens);
45+
@include mdc-switch-theme.theme($mdc-tokens);
46+
@include token-utils.create-token-values(tokens-mat-switch.$prefix, $mat-tokens);
4147

4248
// TODO(wagnermaciel): Use our token system to define this css variable.
4349
--mdc-switch-disabled-label-text-color: #{inspection.get-theme-color(
@@ -71,11 +77,13 @@
7177
@include _theme-from-tokens(inspection.get-theme-tokens($theme, typography));
7278
}
7379
@else {
74-
$mdc-switch-typography-tokens: tokens-mdc-switch.get-typography-tokens($theme);
80+
$mat-tokens: tokens-mat-switch.get-typography-tokens($theme);
81+
$mdc-tokens: tokens-mdc-switch.get-typography-tokens($theme);
7582

7683
// Add values for MDC slide toggle tokens
7784
@include sass-utils.current-selector-or-root() {
78-
@include mdc-switch-theme.theme($mdc-switch-typography-tokens);
85+
@include mdc-switch-theme.theme($mdc-tokens);
86+
@include token-utils.create-token-values(tokens-mat-switch.$prefix, $mat-tokens);
7987

8088
.mat-mdc-slide-toggle {
8189
@include mdc-form-field-theme.theme(tokens-mdc-form-field.get-typography-tokens($theme));
@@ -92,6 +100,8 @@
92100
}
93101
@else {
94102
@include sass-utils.current-selector-or-root() {
103+
$mat-tokens: tokens-mat-switch.get-density-tokens($theme);
104+
$mdc-tokens: tokens-mdc-switch.get-density-tokens($theme);
95105
@include mdc-switch-theme.theme(tokens-mdc-switch.get-density-tokens($theme));
96106
}
97107
}
@@ -123,10 +133,13 @@
123133
}
124134

125135
@mixin _theme-from-tokens($tokens, $options...) {
126-
$mdc-switch-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-switch.$prefix, $options...);
127136
// Don't pass $options here, since the mdc-form-field doesn't support color options,
128137
// only the mdc-switch does.
129138
$mdc-form-field-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-form-field.$prefix);
130-
@include mdc-switch-theme.theme($mdc-switch-tokens);
139+
$mat-switch-tokens: token-utils.get-tokens-for($tokens, tokens-mat-switch.$prefix);
140+
$mdc-switch-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-switch.$prefix, $options...);
141+
131142
@include mdc-form-field-theme.theme($mdc-form-field-tokens);
143+
@include mdc-switch-theme.theme($mdc-switch-tokens);
144+
@include token-utils.create-token-values(tokens-mat-switch.$prefix, $mat-switch-tokens);
132145
}

src/material/slide-toggle/slide-toggle.scss

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
@use '@material/ripple' as mdc-ripple;
66
@use '../core/style/layout-common';
77
@use '@material/theme/custom-properties' as mdc-custom-properties;
8+
@use '../core/tokens/m2/mat/switch' as m2-mat-switch;
89
@use '../core/tokens/m2/mdc/switch' as m2-mdc-switch;
10+
@use '../core/tokens/token-utils';
911

1012
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
1113
$mdc-switch-token-slots: m2-mdc-switch.get-token-slots();
@@ -115,3 +117,67 @@
115117
cursor: pointer;
116118
}
117119
}
120+
121+
// Used for M3 animations. Does not affect the M2 slide-toggle
122+
// because the width and height are static, and the margin is unused.
123+
.mdc-switch__handle {
124+
transition:
125+
width 75ms cubic-bezier(0.4, 0, 0.2, 1),
126+
height 75ms cubic-bezier(0.4, 0, 0.2, 1),
127+
margin 75ms cubic-bezier(0.4, 0, 0.2, 1);
128+
}
129+
130+
@include token-utils.use-tokens(m2-mat-switch.$prefix, m2-mat-switch.get-token-slots()) {
131+
.mat-mdc-slide-toggle {
132+
.mdc-switch--unselected .mdc-switch__handle {
133+
@include token-utils.create-token-slot(width, unselected-handle-size);
134+
@include token-utils.create-token-slot(height, unselected-handle-size);
135+
}
136+
137+
.mdc-switch--selected .mdc-switch__handle {
138+
@include token-utils.create-token-slot(width, selected-handle-size);
139+
@include token-utils.create-token-slot(height, selected-handle-size);
140+
}
141+
142+
.mdc-switch__handle:has(.mdc-switch__icons) {
143+
@include token-utils.create-token-slot(width, with-icon-handle-size);
144+
@include token-utils.create-token-slot(height, with-icon-handle-size);
145+
}
146+
147+
&:active .mdc-switch:not(.mdc-switch--disabled) .mdc-switch__handle {
148+
@include token-utils.create-token-slot(width, pressed-handle-size);
149+
@include token-utils.create-token-slot(height, pressed-handle-size);
150+
}
151+
}
152+
}
153+
154+
@include token-utils.use-tokens(m2-mat-switch.$prefix, m2-mat-switch.get-token-slots()) {
155+
.mat-mdc-slide-toggle {
156+
.mdc-switch--selected .mdc-switch__handle {
157+
@include token-utils.create-token-slot(margin, selected-handle-horizontal-margin);
158+
159+
&:has(.mdc-switch__icons) {
160+
@include token-utils.create-token-slot(margin, selected-with-icon-handle-horizontal-margin);
161+
}
162+
}
163+
164+
.mdc-switch--unselected .mdc-switch__handle {
165+
@include token-utils.create-token-slot(margin, unselected-handle-horizontal-margin);
166+
167+
&:has(.mdc-switch__icons) {
168+
@include token-utils.create-token-slot(
169+
margin,
170+
unselected-with-icon-handle-horizontal-margin,
171+
);
172+
}
173+
}
174+
175+
&:active .mdc-switch--selected:not(.mdc-switch--disabled) .mdc-switch__handle {
176+
@include token-utils.create-token-slot(margin, selected-pressed-handle-horizontal-margin);
177+
}
178+
179+
&:active .mdc-switch--unselected:not(.mdc-switch--disabled) .mdc-switch__handle {
180+
@include token-utils.create-token-slot(margin, unselected-pressed-handle-horizontal-margin);
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)