Skip to content

Commit

Permalink
refactor(material/button): simplify FAB structural styles (#29353)
Browse files Browse the repository at this point in the history
Simplifies the styles of the FAB to make them smaller and easier to maintain.

(cherry picked from commit 35ce605)
  • Loading branch information
crisbeto committed Jul 1, 2024
1 parent ce20aa2 commit 316a2dc
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 142 deletions.
32 changes: 16 additions & 16 deletions src/material/button/_fab-theme.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
@use '@material/fab/fab-theme' as mdc-fab-theme;
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
@use '../core/style/sass-utils';
@use '../core/theming/theming';
@use '../core/theming/inspection';
Expand All @@ -21,13 +18,13 @@
@include _theme-from-tokens(inspection.get-theme-tokens($theme, base));
}
@else {
// Add default values for tokens not related to color, typography, or density.
@include sass-utils.current-selector-or-root() {
@include mdc-fab-theme.theme(tokens-mdc-fab.get-unthemable-tokens());
@include mdc-fab-small-theme.theme(tokens-mdc-fab-small.get-unthemable-tokens());
@include mdc-extended-fab-theme.theme(
tokens-mdc-extended-fab.get-unthemable-tokens()
);
@include token-utils.create-token-values(
tokens-mdc-fab.$prefix, tokens-mdc-fab.get-unthemable-tokens());
@include token-utils.create-token-values(
tokens-mdc-fab-small.$prefix, tokens-mdc-fab-small.get-unthemable-tokens());
@include token-utils.create-token-values(
tokens-mdc-extended-fab.$prefix, tokens-mdc-extended-fab.get-unthemable-tokens());
}
}
}
Expand All @@ -43,7 +40,7 @@
tokens-mat-fab.get-color-tokens($theme)
);

@include mdc-fab-theme.theme($mdc-tokens);
@include token-utils.create-token-values(tokens-mdc-fab.$prefix, $mdc-tokens);
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-tokens);
}

Expand All @@ -58,7 +55,7 @@
tokens-mat-fab-small.get-color-tokens($theme)
);

@include mdc-fab-small-theme.theme($mdc-tokens);
@include token-utils.create-token-values(tokens-mdc-fab-small.$prefix, $mdc-tokens);
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-tokens);
}

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

.mat-mdc-fab {
&.mat-primary {
Expand Down Expand Up @@ -116,7 +114,8 @@
}
@else {
@include sass-utils.current-selector-or-root() {
@include mdc-extended-fab-theme.theme(tokens-mdc-extended-fab.get-typography-tokens($theme));
@include token-utils.create-token-values(tokens-mdc-extended-fab.$prefix,
tokens-mdc-extended-fab.get-typography-tokens($theme));
@include token-utils.create-token-values(tokens-mat-fab.$prefix,
tokens-mat-fab.get-typography-tokens($theme));
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix,
Expand Down Expand Up @@ -190,9 +189,10 @@
$mat-fab-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab.$prefix, $options...);
$mat-fab-small-tokens: token-utils.get-tokens-for($tokens, tokens-mat-fab-small.$prefix,
$options...);
@include mdc-extended-fab-theme.theme($mdc-extended-fab-tokens);
@include mdc-fab-theme.theme($mdc-fab-tokens);
@include mdc-fab-small-theme.theme($mdc-fab-small-tokens);
@include token-utils.create-token-values(tokens-mdc-extended-fab.$prefix,
$mdc-extended-fab-tokens);
@include token-utils.create-token-values(tokens-mdc-fab.$prefix, $mdc-fab-tokens);
@include token-utils.create-token-values(tokens-mdc-fab-small.$prefix, $mdc-fab-small-tokens);
@include token-utils.create-token-values(tokens-mat-fab.$prefix, $mat-fab-tokens);
@include token-utils.create-token-values(tokens-mat-fab-small.$prefix, $mat-fab-small-tokens);
}
4 changes: 2 additions & 2 deletions src/material/button/button-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ const HOST_SELECTOR_MDC_CLASS_PAIR: {attribute: string; mdcClasses: string[]}[]
},
{
attribute: 'mat-fab',
mdcClasses: ['mdc-fab', 'mat-mdc-fab'],
mdcClasses: ['mdc-fab', 'mat-mdc-fab-base', 'mat-mdc-fab'],
},
{
attribute: 'mat-mini-fab',
mdcClasses: ['mdc-fab', 'mdc-fab--mini', 'mat-mdc-mini-fab'],
mdcClasses: ['mdc-fab', 'mat-mdc-fab-base', 'mdc-fab--mini', 'mat-mdc-mini-fab'],
},
{
attribute: 'mat-icon-button',
Expand Down
182 changes: 107 additions & 75 deletions src/material/button/fab.scss
Original file line number Diff line number Diff line change
@@ -1,68 +1,70 @@
@use 'sass:map';
@use '@material/fab' as mdc-fab;
@use '@material/fab/extended-fab-theme' as mdc-extended-fab-theme;
@use '@material/fab/fab-theme' as mdc-fab-theme;
@use '@material/fab/fab-small-theme' as mdc-fab-small-theme;
@use '@material/typography/typography' as mdc-typography;
@use '@material/theme/custom-properties' as mdc-custom-properties;

@use './button-base';
@use '../core/mdc-helpers/mdc-helpers';
@use '../core/tokens/token-utils';
@use '../core/style/private' as style-private;
@use '../core/style/vendor-prefixes';
@use '../core/focus-indicators/private' as focus-indicators-private;
@use '../core/tokens/m2/mdc/extended-fab' as tokens-mdc-extended-fab;
@use '../core/tokens/m2/mdc/fab' as tokens-mdc-fab;
@use '../core/tokens/m2/mat/fab' as tokens-mat-fab;
@use '../core/tokens/m2/mdc/fab-small' as tokens-mdc-fab-small;
@use '../core/tokens/m2/mat/fab-small' as tokens-mat-fab-small;

@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
$mdc-fab-token-slots: tokens-mdc-fab.get-token-slots();
$mdc-fab-small-token-slots: tokens-mdc-fab-small.get-token-slots();
$mdc-extended-fab-token-slots: tokens-mdc-extended-fab.get-token-slots();
$exclude-tokens: (
// Exclude the elevation tokens here since we output them manually below.
container-elevation: null,
focus-container-elevation: null,
hover-container-elevation: null,
pressed-container-elevation: null,
container-shadow-color: null,
);
.mat-mdc-fab-base {
@include button-base.mat-private-button-interactive();
@include style-private.private-animation-noop();
@include vendor-prefixes.user-select(none);
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 56px;
height: 56px;
padding: 0;
border: none;
fill: currentColor;
text-decoration: none;
cursor: pointer;
-moz-appearance: none;
-webkit-appearance: none;
overflow: visible;
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1), opacity 15ms linear 30ms,
transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);
flex-shrink: 0; // Prevent the button from shrinking since it's always supposed to be a circle.

// Note: it's important to pass the query here, otherwise MDC generates
// some unnecessary typography styles for the extended FAB.
@include mdc-fab.static-styles($query: mdc-helpers.$mdc-base-styles-query);
&::before {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
top: 0;
left: 0;
border: 1px solid transparent;
border-radius: inherit;
content: '';
pointer-events: none;
}

.mat-mdc-fab {
@include mdc-fab-theme.theme-styles(map.merge($mdc-fab-token-slots, $exclude-tokens));
// MDC used to include this and it seems like a lot of apps depend on it.
&[hidden] {
display: none;
}

.mat-mdc-mini-fab {
@include mdc-fab-small-theme.theme-styles(
map.merge($mdc-fab-small-token-slots, $exclude-tokens));
&::-moz-focus-inner {
padding: 0;
border: 0;
}

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

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

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

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

.mat-mdc-focus-indicator::before {
Expand All @@ -93,18 +97,18 @@

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

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

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

&:active, &:focus:active {
@include button-base.mat-private-button-elevation(pressed-container-elevation);
@include token-utils.create-token-slot(box-shadow, pressed-container-elevation-shadow);
}
}
}
Expand All @@ -113,10 +117,13 @@
@include button-base.mat-private-button-touch-target(true, $mat-tokens...);
@include button-base.mat-private-button-ripple($mat-tokens...);

@include mdc-helpers.disable-mdc-fallback-declarations {
@include token-utils.use-tokens($mat-tokens...) {
@include token-utils.create-token-slot(color, foreground-color, inherit);
}
@include token-utils.use-tokens($mdc-tokens...) {
@include token-utils.create-token-slot(background-color, container-color);
@include token-utils.create-token-slot(border-radius, container-shape);
}

@include token-utils.use-tokens($mat-tokens...) {
@include token-utils.create-token-slot(color, foreground-color, inherit);
}

@include _fab-elevation($mdc-tokens);
Expand All @@ -137,15 +144,30 @@
}

.mat-mdc-mini-fab {
width: 40px;
height: 40px;

@include _fab-structure(
(tokens-mdc-fab-small.$prefix, tokens-mdc-fab-small.get-token-slots()),
(tokens-mat-fab-small.$prefix, tokens-mat-fab-small.get-token-slots()),
);
}

.mat-mdc-extended-fab {
@include _fab-elevation((tokens-mdc-extended-fab.$prefix,
tokens-mdc-extended-fab.get-token-slots()));
$mdc-tokens: (tokens-mdc-extended-fab.$prefix, tokens-mdc-extended-fab.get-token-slots());

// Before tokens MDC included the font smoothing automatically, but with
// tokens it doesn't. We add it since it can cause tiny differences in
// screenshot tests and it generally looks better.
@include vendor-prefixes.smooth-font();
border-radius: 24px;
padding-left: 20px;
padding-right: 20px;
width: auto;
max-width: 100%;
line-height: normal;

@include _fab-elevation($mdc-tokens);

@include button-base.mat-private-button-disabled {
// Necessary for interactive disabled buttons.
Expand All @@ -154,30 +176,40 @@
}
}

& > .mat-icon,
& > .material-icons { // stylelint-disable-line selector-class-pattern
@include mdc-fab.extended-icon-padding(
mdc-fab.$extended-icon-padding,
mdc-fab.$extended-label-padding
);
@include token-utils.use-tokens($mdc-tokens...) {
@include token-utils.create-token-slot(height, container-height);
@include token-utils.create-token-slot(border-radius, container-shape);
@include token-utils.create-token-slot(font-family, label-text-font);
@include token-utils.create-token-slot(font-size, label-text-size);
@include token-utils.create-token-slot(font-weight, label-text-weight);
@include token-utils.create-token-slot(letter-spacing, label-text-tracking);
}

// stylelint-disable selector-class-pattern
// For Extended FAB with text label followed by icon.
// We are checking for the a button class because white this is a FAB it
// uses the same template as button.
[dir='rtl'] & .mdc-button__label + .mat-icon,
[dir='rtl'] & .mdc-button__label + .material-icons,
> .mat-icon,
> .material-icons {
margin-left: -8px;
margin-right: 12px;
}

.mdc-button__label + .mat-icon,
.mdc-button__label + .material-icons,
[dir='rtl'] & > .mat-icon,
[dir='rtl'] & > .material-icons {
margin-left: 12px;
margin-right: -8px;
}
// stylelint-enable selector-class-pattern

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

// For Extended FAB with text label followed by icon.
// We are checking for the a button class because white this is a FAB it
// uses the same template as button.
// stylelint-disable-next-line selector-class-pattern
.mdc-button__label + .mat-icon, .mdc-button__label + .material-icons {
@include mdc-fab.extended-icon-padding(
mdc-fab.$extended-icon-padding,
mdc-fab.$extended-label-padding,
$is-icon-at-end: true
);
}
}

17 changes: 11 additions & 6 deletions src/material/core/tokens/m2/mdc/_extended-fab.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@use '@material/elevation/elevation-theme' as mdc-elevation;
@use '../../token-utils';
@use '../../../theming/inspection';

Expand Down Expand Up @@ -38,18 +39,22 @@ $prefix: (mdc, extended-fab);
pressed-ripple-color: null,
pressed-ripple-opacity: null,
pressed-state-layer-color: null,
pressed-state-layer-opacity: null
pressed-state-layer-opacity: null,
container-elevation: null,
focus-container-elevation: null,
hover-container-elevation: null,
pressed-container-elevation: null,
container-shadow-color: null,
);
}

// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
@return (
container-elevation: 6,
focus-container-elevation: 8,
hover-container-elevation: 8,
pressed-container-elevation: 12,
container-shadow-color: #000,
container-elevation-shadow: mdc-elevation.elevation-box-shadow(6),
focus-container-elevation-shadow: mdc-elevation.elevation-box-shadow(8),
hover-container-elevation-shadow: mdc-elevation.elevation-box-shadow(8),
pressed-container-elevation-shadow: mdc-elevation.elevation-box-shadow(12),
);
}

Expand Down
Loading

0 comments on commit 316a2dc

Please sign in to comment.