Skip to content

Commit 216ec98

Browse files
committed
refactor(material/button): simplify FAB structural styles
Simplifies the styles of the FAB to make them smaller and easier to maintain.
1 parent 2636512 commit 216ec98

File tree

10 files changed

+217
-143
lines changed

10 files changed

+217
-143
lines changed

src/material/button/_fab-theme.scss

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
@use '@material/fab/fab-theme' as mdc-fab-theme;
2-
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
3-
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
41
@use '../core/style/sass-utils';
52
@use '../core/theming/theming';
63
@use '../core/theming/inspection';
@@ -21,13 +18,13 @@
2118
@include _theme-from-tokens(inspection.get-theme-tokens($theme, base));
2219
}
2320
@else {
24-
// Add default values for tokens not related to color, typography, or density.
2521
@include sass-utils.current-selector-or-root() {
26-
@include mdc-fab-theme.theme(tokens-mdc-fab.get-unthemable-tokens());
27-
@include mdc-fab-small-theme.theme(tokens-mdc-fab-small.get-unthemable-tokens());
28-
@include mdc-extended-fab-theme.theme(
29-
tokens-mdc-extended-fab.get-unthemable-tokens()
30-
);
22+
@include token-utils.create-token-values(
23+
tokens-mdc-fab.$prefix, tokens-mdc-fab.get-unthemable-tokens());
24+
@include token-utils.create-token-values(
25+
tokens-mdc-fab-small.$prefix, tokens-mdc-fab-small.get-unthemable-tokens());
26+
@include token-utils.create-token-values(
27+
tokens-mdc-extended-fab.$prefix, tokens-mdc-extended-fab.get-unthemable-tokens());
3128
}
3229
}
3330
}
@@ -43,7 +40,7 @@
4340
tokens-mat-fab.get-color-tokens($theme)
4441
);
4542

46-
@include mdc-fab-theme.theme($mdc-tokens);
43+
@include token-utils.create-token-values(tokens-mdc-fab.$prefix, $mdc-tokens);
4744
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-tokens);
4845
}
4946

@@ -58,7 +55,7 @@
5855
tokens-mat-fab-small.get-color-tokens($theme)
5956
);
6057

61-
@include mdc-fab-small-theme.theme($mdc-tokens);
58+
@include token-utils.create-token-values(tokens-mdc-fab-small.$prefix, $mdc-tokens);
6259
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-tokens);
6360
}
6461

@@ -75,7 +72,8 @@
7572
@include sass-utils.current-selector-or-root() {
7673
@include _fab-variant($theme, null);
7774
@include _fab-small-variant($theme, null);
78-
@include mdc-extended-fab-theme.theme(tokens-mdc-extended-fab.get-color-tokens($theme));
75+
@include token-utils.create-token-values(
76+
tokens-mdc-extended-fab.$prefix, tokens-mdc-extended-fab.get-color-tokens($theme));
7977

8078
.mat-mdc-fab {
8179
&.mat-primary {
@@ -116,7 +114,8 @@
116114
}
117115
@else {
118116
@include sass-utils.current-selector-or-root() {
119-
@include mdc-extended-fab-theme.theme(tokens-mdc-extended-fab.get-typography-tokens($theme));
117+
@include token-utils.create-token-values(tokens-mdc-extended-fab.$prefix,
118+
tokens-mdc-extended-fab.get-typography-tokens($theme));
120119
@include token-utils.create-token-values(tokens-mat-fab.$prefix,
121120
tokens-mat-fab.get-typography-tokens($theme));
122121
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix,
@@ -190,9 +189,10 @@
190189
$mat-fab-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab.$prefix, $options...);
191190
$mat-fab-small-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab-small.$prefix,
192191
$options...);
193-
@include mdc-extended-fab-theme.theme($mdc-extended-fab-tokens);
194-
@include mdc-fab-theme.theme($mdc-fab-tokens);
195-
@include mdc-fab-small-theme.theme($mdc-fab-small-tokens);
192+
@include token-utils.create-token-values(tokens-mdc-extended-fab.$prefix,
193+
$mdc-extended-fab-tokens);
194+
@include token-utils.create-token-values(tokens-mdc-fab.$prefix, $mdc-fab-tokens);
195+
@include token-utils.create-token-values(tokens-mdc-fab-small.$prefix, $mdc-fab-small-tokens);
196196
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-fab-tokens);
197197
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-fab-small-tokens);
198198
}

src/material/button/button-base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ const HOST_SELECTOR_MDC_CLASS_PAIR: {attribute: string; mdcClasses: string[]}[]
7272
},
7373
{
7474
attribute: 'mat-fab',
75-
mdcClasses: ['mdc-fab', 'mat-mdc-fab'],
75+
mdcClasses: ['mdc-fab', 'mat-mdc-fab-base', 'mat-mdc-fab'],
7676
},
7777
{
7878
attribute: 'mat-mini-fab',
79-
mdcClasses: ['mdc-fab', 'mdc-fab--mini', 'mat-mdc-mini-fab'],
79+
mdcClasses: ['mdc-fab', 'mat-mdc-fab-base', 'mdc-fab--mini', 'mat-mdc-mini-fab'],
8080
},
8181
{
8282
attribute: 'mat-icon-button',

src/material/button/fab.scss

Lines changed: 103 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,65 @@
1-
@use 'sass:map';
2-
@use '@material/fab' as mdc-fab;
3-
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
4-
@use '@material/fab/fab-theme' as mdc-fab-theme;
5-
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
6-
@use '@material/typography/typography' as mdc-typography;
7-
@use '@material/theme/custom-properties' as mdc-custom-properties;
8-
91
@use './button-base';
10-
@use '../core/mdc-helpers/mdc-helpers';
112
@use '../core/tokens/token-utils';
123
@use '../core/style/private' as style-private;
4+
@use '../core/style/vendor-prefixes';
135
@use '../core/focus-indicators/private' as focus-indicators-private;
146
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
157
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
168
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
179
@use '../core/tokens/m2/mdc/fab-small' as tokens-mdc-fab-small;
1810
@use '../core/tokens/m2/mat/fab-small' as tokens-mat-fab-small;
1911

20-
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
21-
$mdc-fab-token-slots: tokens-mdc-fab.get-token-slots();
22-
$mdc-fab-small-token-slots: tokens-mdc-fab-small.get-token-slots();
23-
$mdc-extended-fab-token-slots: tokens-mdc-extended-fab.get-token-slots();
24-
$exclude-tokens: (
25-
// Exclude the elevation tokens here since we output them manually below.
26-
container-elevation: null,
27-
focus-container-elevation: null,
28-
hover-container-elevation: null,
29-
pressed-container-elevation: null,
30-
container-shadow-color: null,
31-
);
32-
33-
// Note: it's important to pass the query here, otherwise MDC generates
34-
// some unnecessary typography styles for the extended FAB.
35-
@include mdc-fab.static-styles($query: mdc-helpers.$mdc-base-styles-query);
12+
.mat-mdc-fab-base {
13+
@include button-base.mat-private-button-interactive();
14+
@include style-private.private-animation-noop();
15+
@include vendor-prefixes.user-select(none);
16+
position: relative;
17+
display: inline-flex;
18+
align-items: center;
19+
justify-content: center;
20+
box-sizing: border-box;
21+
width: 56px;
22+
height: 56px;
23+
padding: 0;
24+
border: none;
25+
fill: currentColor;
26+
text-decoration: none;
27+
cursor: pointer;
28+
-moz-appearance: none;
29+
-webkit-appearance: none;
30+
overflow: visible;
31+
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1), opacity 15ms linear 30ms,
32+
transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);
33+
flex-shrink: 0; // Prevent the button from shrinking since it's always supposed to be a circle.
3634

37-
.mat-mdc-fab {
38-
@include mdc-fab-theme.theme-styles(map.merge($mdc-fab-token-slots, $exclude-tokens));
35+
&::before {
36+
position: absolute;
37+
box-sizing: border-box;
38+
width: 100%;
39+
height: 100%;
40+
top: 0;
41+
left: 0;
42+
border: 1px solid transparent;
43+
border-radius: inherit;
44+
content: '';
45+
pointer-events: none;
3946
}
4047

41-
.mat-mdc-mini-fab {
42-
@include mdc-fab-small-theme.theme-styles(
43-
map.merge($mdc-fab-small-token-slots, $exclude-tokens));
48+
&::-moz-focus-inner {
49+
padding: 0;
50+
border: 0;
4451
}
4552

46-
.mat-mdc-extended-fab {
47-
// Before tokens MDC included the font smoothing automatically, but with
48-
// tokens it doesn't. We add it since it can cause tiny differences in
49-
// screenshot tests and it generally looks better.
50-
@include mdc-typography.smooth-font();
51-
@include mdc-extended-fab-theme.theme-styles(
52-
map.merge($mdc-extended-fab-token-slots, $exclude-tokens));
53+
&:active, &:focus {
54+
outline: none;
5355
}
54-
}
5556

56-
.mat-mdc-fab, .mat-mdc-mini-fab {
57-
@include button-base.mat-private-button-interactive();
58-
@include style-private.private-animation-noop();
59-
flex-shrink: 0; // Prevent the button from shrinking since it's always supposed to be a circle.
57+
&:hover {
58+
cursor: pointer;
59+
}
6060

61-
// MDC adds some styles to fab and mini-fab that conflict with some of our focus indicator
62-
// styles and don't actually do anything. This undoes those conflicting styles.
63-
&:not(.mdc-ripple-upgraded):focus::before {
64-
background: transparent;
65-
opacity: 1;
61+
& > svg {
62+
width: 100%;
6663
}
6764

6865
// MDC expects the fab icon to contain this HTML content:
@@ -73,7 +70,9 @@
7370
// mixin will style the icons appropriately.
7471
// stylelint-disable-next-line selector-class-pattern
7572
.mat-icon, .material-icons {
76-
@include mdc-fab.icon_();
73+
transition: transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);
74+
fill: currentColor;
75+
will-change: transform;
7776
}
7877

7978
.mat-mdc-focus-indicator::before {
@@ -93,18 +92,18 @@
9392

9493
@mixin _fab-elevation($mdc-tokens) {
9594
@include token-utils.use-tokens($mdc-tokens...) {
96-
@include button-base.mat-private-button-elevation(container-elevation);
95+
@include token-utils.create-token-slot(box-shadow, container-elevation-shadow);
9796

9897
&:hover {
99-
@include button-base.mat-private-button-elevation(hover-container-elevation);
98+
@include token-utils.create-token-slot(box-shadow, hover-container-elevation-shadow);
10099
}
101100

102101
&:focus {
103-
@include button-base.mat-private-button-elevation(focus-container-elevation);
102+
@include token-utils.create-token-slot(box-shadow, focus-container-elevation-shadow);
104103
}
105104

106105
&:active, &:focus:active {
107-
@include button-base.mat-private-button-elevation(pressed-container-elevation);
106+
@include token-utils.create-token-slot(box-shadow, pressed-container-elevation-shadow);
108107
}
109108
}
110109
}
@@ -113,10 +112,13 @@
113112
@include button-base.mat-private-button-touch-target(true, $mat-tokens...);
114113
@include button-base.mat-private-button-ripple($mat-tokens...);
115114

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-
}
115+
@include token-utils.use-tokens($mdc-tokens...) {
116+
@include token-utils.create-token-slot(background-color, container-color);
117+
@include token-utils.create-token-slot(border-radius, container-shape);
118+
}
119+
120+
@include token-utils.use-tokens($mat-tokens...) {
121+
@include token-utils.create-token-slot(color, foreground-color, inherit);
120122
}
121123

122124
@include _fab-elevation($mdc-tokens);
@@ -137,15 +139,30 @@
137139
}
138140

139141
.mat-mdc-mini-fab {
142+
width: 40px;
143+
height: 40px;
144+
140145
@include _fab-structure(
141146
(tokens-mdc-fab-small.$prefix, tokens-mdc-fab-small.get-token-slots()),
142147
(tokens-mat-fab-small.$prefix, tokens-mat-fab-small.get-token-slots()),
143148
);
144149
}
145150

146151
.mat-mdc-extended-fab {
147-
@include _fab-elevation((tokens-mdc-extended-fab.$prefix,
148-
tokens-mdc-extended-fab.get-token-slots()));
152+
$mdc-tokens: (tokens-mdc-extended-fab.$prefix, tokens-mdc-extended-fab.get-token-slots());
153+
154+
// Before tokens MDC included the font smoothing automatically, but with
155+
// tokens it doesn't. We add it since it can cause tiny differences in
156+
// screenshot tests and it generally looks better.
157+
@include vendor-prefixes.smooth-font();
158+
border-radius: 24px;
159+
padding-left: 20px;
160+
padding-right: 20px;
161+
width: auto;
162+
max-width: 100%;
163+
line-height: normal;
164+
165+
@include _fab-elevation($mdc-tokens);
149166

150167
@include button-base.mat-private-button-disabled {
151168
// Necessary for interactive disabled buttons.
@@ -154,30 +171,40 @@
154171
}
155172
}
156173

157-
& > .mat-icon,
158-
& > .material-icons { // stylelint-disable-line selector-class-pattern
159-
@include mdc-fab.extended-icon-padding(
160-
mdc-fab.$extended-icon-padding,
161-
mdc-fab.$extended-label-padding
162-
);
174+
@include token-utils.use-tokens($mdc-tokens...) {
175+
@include token-utils.create-token-slot(height, container-height);
176+
@include token-utils.create-token-slot(border-radius, container-shape);
177+
@include token-utils.create-token-slot(font-family, label-text-font);
178+
@include token-utils.create-token-slot(font-size, label-text-size);
179+
@include token-utils.create-token-slot(font-weight, label-text-weight);
180+
@include token-utils.create-token-slot(letter-spacing, label-text-tracking);
181+
}
182+
183+
// stylelint-disable selector-class-pattern
184+
// For Extended FAB with text label followed by icon.
185+
// We are checking for the a button class because white this is a FAB it
186+
// uses the same template as button.
187+
[dir='rtl'] & .mdc-button__label + .mat-icon,
188+
[dir='rtl'] & .mdc-button__label + .material-icons,
189+
> .mat-icon,
190+
> .material-icons {
191+
margin-left: -8px;
192+
margin-right: 12px;
163193
}
164194

195+
.mdc-button__label + .mat-icon,
196+
.mdc-button__label + .material-icons,
197+
[dir='rtl'] & > .mat-icon,
198+
[dir='rtl'] & > .material-icons {
199+
margin-left: 12px;
200+
margin-right: -8px;
201+
}
202+
// stylelint-enable selector-class-pattern
203+
165204
// All FABs are square except the extended ones so we
166205
// need to set the touch target back to full-width.
167206
.mat-mdc-button-touch-target {
168207
width: 100%;
169208
}
170-
171-
// For Extended FAB with text label followed by icon.
172-
// We are checking for the a button class because white this is a FAB it
173-
// uses the same template as button.
174-
// stylelint-disable-next-line selector-class-pattern
175-
.mdc-button__label + .mat-icon, .mdc-button__label + .material-icons {
176-
@include mdc-fab.extended-icon-padding(
177-
mdc-fab.$extended-icon-padding,
178-
mdc-fab.$extended-label-padding,
179-
$is-icon-at-end: true
180-
);
181-
}
182209
}
183210

src/material/core/tokens/m2/mdc/_extended-fab.scss

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@use '@material/elevation/elevation-theme' as mdc-elevation;
12
@use '../../token-utils';
23
@use '../../../theming/inspection';
34

@@ -38,18 +39,22 @@ $prefix: (mdc, extended-fab);
3839
pressed-ripple-color: null,
3940
pressed-ripple-opacity: null,
4041
pressed-state-layer-color: null,
41-
pressed-state-layer-opacity: null
42+
pressed-state-layer-opacity: null,
43+
container-elevation: null,
44+
focus-container-elevation: null,
45+
hover-container-elevation: null,
46+
pressed-container-elevation: null,
47+
container-shadow-color: null,
4248
);
4349
}
4450

4551
// Tokens that can be configured through Angular Material's color theming API.
4652
@function get-color-tokens($theme) {
4753
@return (
48-
container-elevation: 6,
49-
focus-container-elevation: 8,
50-
hover-container-elevation: 8,
51-
pressed-container-elevation: 12,
52-
container-shadow-color: #000,
54+
container-elevation-shadow: mdc-elevation.elevation-box-shadow(6),
55+
focus-container-elevation-shadow: mdc-elevation.elevation-box-shadow(8),
56+
hover-container-elevation-shadow: mdc-elevation.elevation-box-shadow(8),
57+
pressed-container-elevation-shadow: mdc-elevation.elevation-box-shadow(12),
5358
);
5459
}
5560

0 commit comments

Comments
 (0)