Skip to content

Commit ca431d3

Browse files
committed
refactor(material/button): clean up fab tokens (#27994)
Reworks the tokens setup for the FAB by: * Introducing a custom tokens map. It was necessary both for these changes and will come in handy later for the ripples. * Using tokens specifically for the disabled state instead of passing in the non-disabled ones. This aligns the FAB with the rest of the library and allows us to reduce the specificity. * Introducing a tokens specifically for the icon/text color. Currently we have an ad-hoc variable declared directly in the component styles. * Using our own mixins for the elevation instead of MDC's. Our mixin calls into MDC eventually, but it has some safeguards as well. * Generating the tokens that we pass into MDC's theme using our APIs, instead of creating the map directly. (cherry picked from commit e9fc04d)
1 parent 520343f commit ca431d3

File tree

4 files changed

+117
-69
lines changed

4 files changed

+117
-69
lines changed

src/material/button/_fab-theme.scss

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
@use '../core/theming/inspection';
1010
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
1111
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
12+
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
13+
@use '../core/tokens/token-utils';
1214
@use '../core/typography/typography';
1315

1416
@mixin base($theme) {
@@ -21,37 +23,25 @@
2123
}
2224
}
2325

24-
@mixin _fab-variant($foreground, $background) {
25-
$color-tokens: (
26-
container-color: $background,
27-
icon-color: $foreground
26+
@mixin _fab-variant($theme, $palette) {
27+
$mdc-tokens: if($palette,
28+
tokens-mdc-fab.private-get-color-palette-color-tokens($theme, $palette),
29+
tokens-mdc-fab.get-color-tokens($theme)
2830
);
29-
@include mdc-fab-theme.theme($color-tokens);
3031

31-
--mat-mdc-fab-color: #{$foreground};
32-
}
32+
$mat-tokens: if($palette,
33+
tokens-mat-fab.private-get-color-palette-color-tokens($theme, $palette),
34+
tokens-mat-fab.get-color-tokens($theme)
35+
);
3336

34-
@function white-or-black($color, $is-dark) {
35-
@return if(mdc-helpers.variable-safe-contrast-tone($color, $is-dark) == 'dark', #000, #fff);
37+
@include mdc-fab-theme.theme($mdc-tokens);
38+
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-tokens);
3639
}
3740

3841
@mixin color($theme) {
39-
$is-dark: inspection.get-theme-type($theme) == dark;
40-
41-
$surface: inspection.get-theme-color($theme, background, card);
42-
$primary: inspection.get-theme-color($theme, primary);
43-
$accent: inspection.get-theme-color($theme, accent);
44-
$warn: inspection.get-theme-color($theme, warn);
45-
46-
$on-surface: white-or-black($surface, $is-dark);
47-
$on-primary: white-or-black($primary, $is-dark);
48-
$on-accent: white-or-black($accent, $is-dark);
49-
$on-warn: white-or-black($warn, $is-dark);
50-
51-
$disabled: rgba($on-surface, 0.12);
52-
$on-disabled: rgba($on-surface, if($is-dark, 0.5, 0.38));
53-
5442
@include sass-utils.current-selector-or-root() {
43+
@include _fab-variant($theme, null);
44+
5545
// TODO(wagnermaciel): The ripple-theme-styles mixin depends heavily on
5646
// being wrapped by using-mdc-theme. This workaround needs to be
5747
// revisited w/ a more holistic solution.
@@ -60,28 +50,18 @@
6050
@include mdc-helpers.using-mdc-theme($theme) {
6151
@include button-theme-private.ripple-theme-styles($theme, true);
6252
}
63-
}
6453

65-
:disabled, a[disabled='true'] {
66-
@include button-theme-private.apply-disabled-style() {
67-
@include _fab-variant($on-disabled, $disabled);
54+
&.mat-primary {
55+
@include _fab-variant($theme, primary);
6856
}
69-
}
70-
71-
.mat-unthemed {
72-
@include _fab-variant($on-surface, $surface);
73-
}
74-
75-
.mat-primary {
76-
@include _fab-variant($on-primary, $primary);
77-
}
7857

79-
.mat-accent {
80-
@include _fab-variant($on-accent, $accent);
81-
}
58+
&.mat-accent {
59+
@include _fab-variant($theme, accent);
60+
}
8261

83-
.mat-warn {
84-
@include _fab-variant($on-warn, $warn);
62+
&.mat-warn {
63+
@include _fab-variant($theme, warn);
64+
}
8565
}
8666
}
8767
}

src/material/button/fab.scss

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
@use '@material/fab' as mdc-fab;
22
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
33
@use '@material/fab/fab-theme' as mdc-fab-theme;
4-
@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
54
@use '@material/theme/custom-properties' as mdc-custom-properties;
65

76
@use './button-base';
7+
@use '../core/style/elevation';
88
@use '../core/mdc-helpers/mdc-helpers';
9+
@use '../core/tokens/token-utils';
910
@use '../core/style/private' as style-private;
1011
@use '../core/focus-indicators/private' as focus-indicators-private;
11-
@use '../core/tokens/m2/mdc/extended-fab' as m2-mdc-extended-fab;
12-
@use '../core/tokens/m2/mdc/fab' as m2-mdc-fab;
12+
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
13+
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
14+
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
1315

1416
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
15-
$mdc-fab-token-slots: m2-mdc-fab.get-token-slots();
16-
$mdc-extended-fab-token-slots: m2-mdc-extended-fab.get-token-slots();
17+
$mdc-fab-token-slots: tokens-mdc-fab.get-token-slots();
18+
$mdc-extended-fab-token-slots: tokens-mdc-extended-fab.get-token-slots();
1719

1820
// Add the MDC fab static styles.
1921
@include mdc-fab.static-styles();
@@ -34,33 +36,31 @@
3436
@include button-base.mat-private-button-interactive();
3537
@include button-base.mat-private-button-touch-target(true);
3638
@include style-private.private-animation-noop();
39+
@include elevation.elevation(6);
40+
flex-shrink: 0; // Prevent the button from shrinking since it's always supposed to be a circle.
3741

3842
@include mdc-helpers.disable-mdc-fallback-declarations {
39-
// TODO(crisbeto): the elevation can be controlled using `container-elevation` in `theme-styles`
40-
// however when it is passed in, MDC throws an error that `container-shadow-color` isn't
41-
// passed in. When `container-shadow-color` is passed in, MDC throws another error, because
42-
// the produced value isn't valid CSS. Eventually we should switch to it once it's fixed.
43-
@include mdc-elevation-theme.elevation(6);
44-
45-
&:hover, &:focus {
46-
@include mdc-elevation-theme.elevation(8);
43+
@include token-utils.use-tokens(tokens-mat-fab.$prefix, tokens-mat-fab.get-token-slots()) {
44+
@include token-utils.create-token-slot(color, foreground-color, inherit);
4745
}
46+
}
4847

49-
&:active, &:focus:active {
50-
@include mdc-elevation-theme.elevation(12);
51-
}
48+
&:hover, &:focus {
49+
@include elevation.elevation(8);
50+
}
5251

53-
@include button-base.mat-private-button-disabled {
54-
@include mdc-elevation-theme.elevation(0);
55-
}
52+
&:active, &:focus:active {
53+
@include elevation.elevation(12);
5654
}
5755

58-
// TODO(crisbeto): `theme-styles` doesn't allow for the color to be controlled. Define a custom
59-
// variable for now so we have something to target.
60-
color: var(--mat-mdc-fab-color, inherit);
56+
@include button-base.mat-private-button-disabled {
57+
@include elevation.elevation(0);
6158

62-
// Prevent the button from shrinking since it's always supposed to be a circle.
63-
flex-shrink: 0;
59+
@include token-utils.use-tokens(tokens-mat-fab.$prefix, tokens-mat-fab.get-token-slots()) {
60+
@include token-utils.create-token-slot(color, disabled-state-foreground-color);
61+
@include token-utils.create-token-slot(background-color, disabled-state-container-color);
62+
}
63+
}
6464

6565
// MDC adds some styles to fab and mini-fab that conflict with some of our focus indicator
6666
// styles and don't actually do anything. This undoes those conflicting styles.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
@use '../../token-utils';
2+
@use '../../../theming/inspection';
3+
@use '../../../style/sass-utils';
4+
5+
// The prefix used to generate the fully qualified name for tokens in this file.
6+
$prefix: (mat, fab);
7+
8+
// Tokens that can't be configured through Angular Material's current theming API,
9+
// but may be in a future version of the theming API.
10+
@function get-unthemable-tokens() {
11+
@return ();
12+
}
13+
14+
// Tokens that can be configured through Angular Material's color theming API.
15+
@function get-color-tokens($theme) {
16+
$is-dark: inspection.get-theme-type($theme) == dark;
17+
$surface: if($is-dark, #fff, #000);
18+
19+
@return (
20+
// Color of icons and text projected into a FAB.
21+
foreground-color: inspection.get-theme-color($theme, foreground, base),
22+
23+
// MDC doesn't have tokens for disabled FABs so we need to implemented them ourselves.
24+
// Background color of the container when the FAB is disabled.
25+
disabled-state-container-color: rgba($surface, 0.12),
26+
// Color of the icons and projected text when the FAB is disabled.
27+
disabled-state-foreground-color: rgba($surface, if($is-dark, 0.5, 0.38)),
28+
);
29+
}
30+
31+
// Generates the mapping for the properties that change based on the FAB palette color.
32+
@function private-get-color-palette-color-tokens($theme, $palette-name) {
33+
@return (
34+
foreground-color: inspection.get-theme-color($theme, $palette-name, default-contrast),
35+
);
36+
}
37+
38+
// Tokens that can be configured through Angular Material's typography theming API.
39+
@function get-typography-tokens($theme) {
40+
@return ();
41+
}
42+
43+
// Tokens that can be configured through Angular Material's density theming API.
44+
@function get-density-tokens($theme) {
45+
@return ();
46+
}
47+
48+
// Combines the tokens generated by the above functions into a single map with placeholder values.
49+
// This is used to create token slots.
50+
@function get-token-slots() {
51+
@return sass-utils.deep-merge-all(
52+
get-unthemable-tokens(),
53+
get-color-tokens(token-utils.$placeholder-color-config),
54+
get-typography-tokens(token-utils.$placeholder-typography-config),
55+
get-density-tokens(token-utils.$placeholder-density-config)
56+
);
57+
}

src/material/core/tokens/m2/mdc/_fab.scss

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ $ripple-target: '.mdc-fab__ripple';
2222
container-shape: 50%,
2323
icon-size: 24px,
2424

25+
// We don't use this token, because it doesn't set the color of any text inside the FAB.
26+
// We create a custom token for it instead.
27+
icon-color: null,
28+
2529
container-elevation: null,
2630
container-height: null,
2731
container-shadow-color: null,
@@ -56,10 +60,17 @@ $ripple-target: '.mdc-fab__ripple';
5660

5761
// Tokens that can be configured through Angular Material's color theming API.
5862
@function get-color-tokens($theme) {
59-
$surface: inspection.get-theme-color($theme, primary, default);
60-
$on-surface: inspection.get-theme-color($theme, primary, default-contrast);
63+
@return (
64+
// Background color of the FAB.
65+
container-color: inspection.get-theme-color($theme, background, card),
66+
);
67+
}
6168

62-
@return (container-color: $surface, icon-color: $on-surface);
69+
// Generates the mapping for the properties that change based on the FAB palette color.
70+
@function private-get-color-palette-color-tokens($theme, $palette-name) {
71+
@return (
72+
container-color: inspection.get-theme-color($theme, $palette-name, default),
73+
);
6374
}
6475

6576
// Tokens that can be configured through Angular Material's typography theming API.

0 commit comments

Comments
 (0)