Skip to content

Commit a496855

Browse files
committed
fix(material/button): generate separate tokens for mini fab
Currently the mini FAB uses the same tokens as the regular one. This is incorrect and causes inconsistencies in M3. These changes split the mini FAB out into its own set of tokens.
1 parent 0cf81f3 commit a496855

File tree

10 files changed

+359
-60
lines changed

10 files changed

+359
-60
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,47 @@
355355
));
356356
}
357357

358+
/// Generates custom tokens for the mat-mini-fab.
359+
/// @param {Map} $systems The MDC system tokens
360+
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
361+
/// @return {Map} A set of custom tokens for the mat-mini-fab
362+
@function fab-small($systems, $exclude-hardcoded) {
363+
@return ((
364+
foreground-color: map.get($systems, md-sys-color, on-primary-container),
365+
state-layer-color: map.get($systems, md-sys-color, primary-container),
366+
ripple-color: mat.private-safe-color-change(
367+
map.get($systems, md-sys-color, on-primary-container),
368+
$alpha: map.get($systems, md-sys-state, pressed-state-layer-opacity)
369+
),
370+
hover-state-layer-opacity: map.get($systems, md-sys-state, hover-state-layer-opacity),
371+
focus-state-layer-opacity: map.get($systems, md-sys-state, focus-state-layer-opacity),
372+
pressed-state-layer-opacity: map.get($systems, md-sys-state, pressed-state-layer-opacity),
373+
disabled-state-container-color: mat.private-safe-color-change(
374+
map.get($systems, md-sys-color, on-surface), $alpha: 0.12),
375+
disabled-state-foreground-color: mat.private-safe-color-change(
376+
map.get($systems, md-sys-color, on-surface), $alpha: 0.38),
377+
), (
378+
// Color variants
379+
primary: (), // Default, no overrides needed.
380+
secondary: (
381+
foreground-color: map.get($systems, md-sys-color, on-secondary-container),
382+
state-layer-color: map.get($systems, md-sys-color, secondary-container),
383+
ripple-color: mat.private-safe-color-change(
384+
map.get($systems, md-sys-color, on-secondary-container),
385+
$alpha: map.get($systems, md-sys-state, pressed-state-layer-opacity)
386+
),
387+
),
388+
tertiary: (
389+
foreground-color: map.get($systems, md-sys-color, on-tertiary-container),
390+
state-layer-color: map.get($systems, md-sys-color, tertiary-container),
391+
ripple-color: mat.private-safe-color-change(
392+
map.get($systems, md-sys-color, on-tertiary-container),
393+
$alpha: map.get($systems, md-sys-state, pressed-state-layer-opacity)
394+
),
395+
)
396+
));
397+
}
398+
358399
/// Generates custom tokens for the mat-form-field.
359400
/// @param {Map} $systems The MDC system tokens
360401
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ $_density-tokens: (
2727
(mdc, elevated-card): (),
2828
(mdc, extended-fab): (),
2929
(mdc, fab): (),
30+
(mdc, fab-small): (),
3031
(mdc, filled-text-field): (),
3132
(mdc, text-button): (
3233
container-height: (40px, 36px, 32px, 28px),

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,19 @@
503503
),
504504
$token-slots
505505
),
506+
_namespace-tokens(
507+
(mdc, fab-small),
508+
(
509+
mdc-tokens.md-comp-fab-primary-small-values($systems, $exclude-hardcoded),
510+
(
511+
// Color variants
512+
primary: (), // Default, no overrides needed.
513+
secondary: mdc-tokens.md-comp-fab-secondary-small-values($systems, $exclude-hardcoded),
514+
tertiary: mdc-tokens.md-comp-fab-tertiary-small-values($systems, $exclude-hardcoded)
515+
)
516+
),
517+
$token-slots
518+
),
506519
_namespace-tokens(
507520
(mdc, extended-fab),
508521
(
@@ -703,6 +716,11 @@
703716
custom-tokens.fab($systems, $exclude-hardcoded),
704717
$token-slots
705718
),
719+
_namespace-tokens(
720+
(mat, fab-small),
721+
custom-tokens.fab-small($systems, $exclude-hardcoded),
722+
$token-slots
723+
),
706724
_namespace-tokens(
707725
(mat, form-field),
708726
custom-tokens.form-field($systems, $exclude-hardcoded),

src/material/button/_fab-theme.scss

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
@use '@material/fab/fab-theme' as mdc-fab-theme;
2+
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
23
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
34
@use '../core/style/sass-utils';
45
@use '../core/theming/theming';
56
@use '../core/theming/inspection';
67
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
8+
@use '../core/tokens/m2/mdc/fab-small' as tokens-mdc-fab-small;
79
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
810
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
11+
@use '../core/tokens/m2/mat/fab-small' as tokens-mat-fab-small;
912
@use '../core/tokens/token-utils';
1013
@use '../core/typography/typography';
1114

@@ -20,6 +23,7 @@
2023
// Add default values for tokens not related to color, typography, or density.
2124
@include sass-utils.current-selector-or-root() {
2225
@include mdc-fab-theme.theme(tokens-mdc-fab.get-unthemable-tokens());
26+
@include mdc-fab-small-theme.theme(tokens-mdc-fab-small.get-unthemable-tokens());
2327
@include mdc-extended-fab-theme.theme(
2428
tokens-mdc-extended-fab.get-unthemable-tokens()
2529
);
@@ -42,6 +46,21 @@
4246
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-tokens);
4347
}
4448

49+
@mixin _fab-small-variant($theme, $palette) {
50+
$mdc-tokens: if($palette,
51+
tokens-mdc-fab-small.private-get-color-palette-color-tokens($theme, $palette),
52+
tokens-mdc-fab-small.get-color-tokens($theme)
53+
);
54+
55+
$mat-tokens: if($palette,
56+
tokens-mat-fab-small.private-get-color-palette-color-tokens($theme, $palette),
57+
tokens-mat-fab-small.get-color-tokens($theme)
58+
);
59+
60+
@include mdc-fab-small-theme.theme($mdc-tokens);
61+
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-tokens);
62+
}
63+
4564
/// Outputs color theme styles for the mat-fab.
4665
/// @param {Map} $theme The theme to generate color styles for.
4766
/// @param {ArgList} Additional optional arguments (only supported for M3 themes):
@@ -54,10 +73,10 @@
5473
@else {
5574
@include sass-utils.current-selector-or-root() {
5675
@include _fab-variant($theme, null);
76+
@include _fab-small-variant($theme, null);
5777
@include mdc-extended-fab-theme.theme(tokens-mdc-extended-fab.get-color-tokens($theme));
5878

59-
.mat-mdc-fab,
60-
.mat-mdc-mini-fab {
79+
.mat-mdc-fab {
6180
&.mat-primary {
6281
@include _fab-variant($theme, primary);
6382
}
@@ -70,6 +89,20 @@
7089
@include _fab-variant($theme, warn);
7190
}
7291
}
92+
93+
.mat-mdc-mini-fab {
94+
&.mat-primary {
95+
@include _fab-small-variant($theme, primary);
96+
}
97+
98+
&.mat-accent {
99+
@include _fab-small-variant($theme, accent);
100+
}
101+
102+
&.mat-warn {
103+
@include _fab-small-variant($theme, warn);
104+
}
105+
}
73106
}
74107
}
75108
}
@@ -85,6 +118,8 @@
85118
@include mdc-extended-fab-theme.theme(tokens-mdc-extended-fab.get-typography-tokens($theme));
86119
@include token-utils.create-token-values(tokens-mat-fab.$prefix,
87120
tokens-mat-fab.get-typography-tokens($theme));
121+
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix,
122+
tokens-mat-fab-small.get-typography-tokens($theme));
88123
}
89124
}
90125
}
@@ -99,6 +134,8 @@
99134
@include sass-utils.current-selector-or-root() {
100135
@include token-utils.create-token-values(tokens-mat-fab.$prefix,
101136
tokens-mat-fab.get-density-tokens($theme));
137+
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix,
138+
tokens-mat-fab-small.get-density-tokens($theme));
102139
}
103140
}
104141
}
@@ -132,8 +169,14 @@
132169
$mdc-extended-fab-tokens: token-utils.get-tokens-for(
133170
$tokens, tokens-mdc-extended-fab.$prefix, $options...);
134171
$mdc-fab-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-fab.$prefix, $options...);
172+
$mdc-fab-small-tokens: token-utils.get-tokens-for($tokens, tokens-mdc-fab-small.$prefix,
173+
$options...);
135174
$mat-fab-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab.$prefix, $options...);
175+
$mat-fab-small-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab-small.$prefix,
176+
$options...);
136177
@include mdc-extended-fab-theme.theme($mdc-extended-fab-tokens);
137178
@include mdc-fab-theme.theme($mdc-fab-tokens);
179+
@include mdc-fab-small-theme.theme($mdc-fab-small-tokens);
138180
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-fab-tokens);
181+
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-fab-small-tokens);
139182
}

src/material/button/fab.scss

Lines changed: 64 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
@use '@material/fab' as mdc-fab;
33
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
44
@use '@material/fab/fab-theme' as mdc-fab-theme;
5+
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
56
@use '@material/typography/typography' as mdc-typography;
67
@use '@material/theme/custom-properties' as mdc-custom-properties;
78

@@ -13,9 +14,12 @@
1314
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
1415
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
1516
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
17+
@use '../core/tokens/m2/mdc/fab-small' as tokens-mdc-fab-small;
18+
@use '../core/tokens/m2/mat/fab-small' as tokens-mat-fab-small;
1619

1720
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
1821
$mdc-fab-token-slots: tokens-mdc-fab.get-token-slots();
22+
$mdc-fab-small-token-slots: tokens-mdc-fab-small.get-token-slots();
1923
$mdc-extended-fab-token-slots: tokens-mdc-extended-fab.get-token-slots();
2024
$exclude-tokens: (
2125
// Exclude the elevation tokens here since we output them manually below.
@@ -30,10 +34,15 @@
3034
// some unnecessary typography styles for the extended FAB.
3135
@include mdc-fab.static-styles($query: mdc-helpers.$mdc-base-styles-query);
3236

33-
.mat-mdc-fab, .mat-mdc-mini-fab {
37+
.mat-mdc-fab {
3438
@include mdc-fab-theme.theme-styles(map.merge($mdc-fab-token-slots, $exclude-tokens));
3539
}
3640

41+
.mat-mdc-mini-fab {
42+
@include mdc-fab-small-theme.theme-styles(
43+
map.merge($mdc-fab-small-token-slots, $exclude-tokens));
44+
}
45+
3746
.mat-mdc-extended-fab {
3847
// Before tokens MDC included the font smoothing automatically, but with
3948
// tokens it doesn't. We add it since it can cause tiny differences in
@@ -46,47 +55,9 @@
4655

4756
.mat-mdc-fab, .mat-mdc-mini-fab {
4857
@include button-base.mat-private-button-interactive();
49-
@include button-base.mat-private-button-touch-target(true, tokens-mat-fab.$prefix,
50-
tokens-mat-fab.get-token-slots());
51-
@include button-base.mat-private-button-ripple(tokens-mat-fab.$prefix,
52-
tokens-mat-fab.get-token-slots());
5358
@include style-private.private-animation-noop();
5459
flex-shrink: 0; // Prevent the button from shrinking since it's always supposed to be a circle.
5560

56-
@include mdc-helpers.disable-mdc-fallback-declarations {
57-
@include token-utils.use-tokens(tokens-mat-fab.$prefix, tokens-mat-fab.get-token-slots()) {
58-
@include token-utils.create-token-slot(color, foreground-color, inherit);
59-
}
60-
}
61-
62-
@include token-utils.use-tokens(tokens-mdc-fab.$prefix, tokens-mdc-fab.get-token-slots()) {
63-
@include button-base.mat-private-button-elevation(container-elevation);
64-
65-
&:hover {
66-
@include button-base.mat-private-button-elevation(hover-container-elevation);
67-
}
68-
69-
&:focus {
70-
@include button-base.mat-private-button-elevation(focus-container-elevation);
71-
}
72-
73-
&:active, &:focus:active {
74-
@include button-base.mat-private-button-elevation(pressed-container-elevation);
75-
}
76-
}
77-
78-
@include button-base.mat-private-button-disabled {
79-
// Necessary for interactive disabled buttons.
80-
&, &:focus {
81-
box-shadow: none;
82-
}
83-
84-
@include token-utils.use-tokens(tokens-mat-fab.$prefix, tokens-mat-fab.get-token-slots()) {
85-
@include token-utils.create-token-slot(color, disabled-state-foreground-color);
86-
@include token-utils.create-token-slot(background-color, disabled-state-container-color);
87-
}
88-
}
89-
9061
// MDC adds some styles to fab and mini-fab that conflict with some of our focus indicator
9162
// styles and don't actually do anything. This undoes those conflicting styles.
9263
&:not(.mdc-ripple-upgraded):focus::before {
@@ -111,11 +82,17 @@
11182
$offset: calc(#{$border-width} + 2px);
11283
margin: calc(#{$offset} * -1);
11384
}
85+
86+
@include button-base.mat-private-button-disabled {
87+
// Necessary for interactive disabled buttons.
88+
&, &:focus {
89+
box-shadow: none;
90+
}
91+
}
11492
}
11593

116-
.mat-mdc-extended-fab {
117-
@include token-utils.use-tokens(tokens-mdc-extended-fab.$prefix,
118-
tokens-mdc-extended-fab.get-token-slots()) {
94+
@mixin _fab-elevation($mdc-tokens) {
95+
@include token-utils.use-tokens($mdc-tokens...) {
11996
@include button-base.mat-private-button-elevation(container-elevation);
12097

12198
&:hover {
@@ -130,6 +107,45 @@
130107
@include button-base.mat-private-button-elevation(pressed-container-elevation);
131108
}
132109
}
110+
}
111+
112+
@mixin _fab-structure($mdc-tokens, $mat-tokens) {
113+
@include button-base.mat-private-button-touch-target(true, $mat-tokens...);
114+
@include button-base.mat-private-button-ripple($mat-tokens...);
115+
116+
@include mdc-helpers.disable-mdc-fallback-declarations {
117+
@include token-utils.use-tokens($mat-tokens...) {
118+
@include token-utils.create-token-slot(color, foreground-color, inherit);
119+
}
120+
}
121+
122+
@include _fab-elevation($mdc-tokens);
123+
124+
@include button-base.mat-private-button-disabled {
125+
@include token-utils.use-tokens($mat-tokens...) {
126+
@include token-utils.create-token-slot(color, disabled-state-foreground-color);
127+
@include token-utils.create-token-slot(background-color, disabled-state-container-color);
128+
}
129+
}
130+
}
131+
132+
.mat-mdc-fab {
133+
@include _fab-structure(
134+
(tokens-mdc-fab.$prefix, tokens-mdc-fab.get-token-slots()),
135+
(tokens-mat-fab.$prefix, tokens-mat-fab.get-token-slots()),
136+
);
137+
}
138+
139+
.mat-mdc-mini-fab {
140+
@include _fab-structure(
141+
(tokens-mdc-fab-small.$prefix, tokens-mdc-fab-small.get-token-slots()),
142+
(tokens-mat-fab-small.$prefix, tokens-mat-fab-small.get-token-slots()),
143+
);
144+
}
145+
146+
.mat-mdc-extended-fab {
147+
@include _fab-elevation((tokens-mdc-extended-fab.$prefix,
148+
tokens-mdc-extended-fab.get-token-slots()));
133149

134150
@include button-base.mat-private-button-disabled {
135151
// Necessary for interactive disabled buttons.
@@ -146,6 +162,12 @@
146162
);
147163
}
148164

165+
// All FABs are square except the extended ones so we
166+
// need to set the touch target back to full-width.
167+
.mat-mdc-button-touch-target {
168+
width: 100%;
169+
}
170+
149171
// For Extended FAB with text label followed by icon.
150172
// We are checking for the a button class because white this is a FAB it
151173
// uses the same template as button.
@@ -159,8 +181,3 @@
159181
}
160182
}
161183

162-
// All FABs are square except the extended ones so we
163-
// need to set the touch target back to full-width.
164-
.mat-mdc-extended-fab .mat-mdc-button-touch-target {
165-
width: 100%;
166-
}

0 commit comments

Comments
 (0)