Skip to content

Commit

Permalink
refactor(material/snack-bar): clean up structural styles
Browse files Browse the repository at this point in the history
Cleans up the snack bar's structural styles to make them smaller and easier to maintain.
  • Loading branch information
crisbeto committed May 31, 2024
1 parent 3b96730 commit 5cc8c2c
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 88 deletions.
23 changes: 16 additions & 7 deletions src/material/snack-bar/_snack-bar-theme.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@use 'sass:map';
@use '@material/snackbar/snackbar-theme' as mdc-snackbar-theme;
@use '../core/theming/theming';
@use '../core/theming/inspection';
@use '../core/theming/validation';
Expand All @@ -16,7 +15,10 @@
@else {
// Add default values for tokens not related to color, typography, or density.
@include sass-utils.current-selector-or-root() {
@include mdc-snackbar-theme.theme(tokens-mdc-snack-bar.get-unthemable-tokens());
@include token-utils.create-token-values(
tokens-mdc-snack-bar.$prefix,
tokens-mdc-snack-bar.get-unthemable-tokens()
);
}
}
}
Expand All @@ -27,10 +29,13 @@
}
@else {
@include sass-utils.current-selector-or-root() {
@include mdc-snackbar-theme.theme(tokens-mdc-snack-bar.get-color-tokens($theme));
@include token-utils.create-token-values(
tokens-mat-snack-bar.$prefix,
tokens-mat-snack-bar.get-color-tokens($theme)
tokens-mdc-snack-bar.$prefix,
tokens-mdc-snack-bar.get-color-tokens($theme)
);
@include token-utils.create-token-values(
tokens-mat-snack-bar.$prefix,
tokens-mat-snack-bar.get-color-tokens($theme)
);
}
}
Expand All @@ -42,7 +47,10 @@
}
@else {
@include sass-utils.current-selector-or-root() {
@include mdc-snackbar-theme.theme(tokens-mdc-snack-bar.get-typography-tokens($theme));
@include token-utils.create-token-values(
tokens-mdc-snack-bar.$prefix,
tokens-mdc-snack-bar.get-typography-tokens($theme)
);
}
}
}
Expand Down Expand Up @@ -83,7 +91,8 @@
@include validation.selector-defined(
'Calls to Angular Material theme mixins with an M3 theme must be wrapped in a selector');
@if ($tokens != ()) {
@include mdc-snackbar-theme.theme(map.get($tokens, tokens-mdc-snack-bar.$prefix));
@include token-utils.create-token-values(
tokens-mdc-snack-bar.$prefix, map.get($tokens, tokens-mdc-snack-bar.$prefix));
@include token-utils.create-token-values(
tokens-mat-snack-bar.$prefix, map.get($tokens, tokens-mat-snack-bar.$prefix));
}
Expand Down
2 changes: 1 addition & 1 deletion src/material/snack-bar/snack-bar-container.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="mdc-snackbar__surface">
<div class="mdc-snackbar__surface mat-mdc-snackbar-surface">
<!--
This outer label wrapper will have the class `mdc-snackbar__label` applied if
the attached template/component does not contain it.
Expand Down
180 changes: 101 additions & 79 deletions src/material/snack-bar/snack-bar-container.scss
Original file line number Diff line number Diff line change
@@ -1,92 +1,95 @@
@use '@material/snackbar/snackbar' as mdc-snackbar;
@use '@material/snackbar/snackbar-theme' as mdc-snackbar-theme;
@use '@material/theme/custom-properties' as mdc-custom-properties;
@use '@angular/cdk';
@use '../core/tokens/m2/mdc/snack-bar' as tokens-mdc-snack-bar;
@use '../core/tokens/m2/mat/snack-bar' as tokens-mat-snack-bar;
@use '../core/tokens/m2/mat/text-button' as tokens-mat-text-button;
@use '../core/tokens/token-utils';
@use '../core/mdc-helpers/mdc-helpers';

@mixin _container-min-width {
$min-width: mdc-snackbar-theme.$min-width;
$mobile-breakpoint: mdc-snackbar-theme.$mobile-breakpoint;

// The styles weren't included in `static-styles` so we need to add them ourselves.
@include mdc-snackbar-theme.min-width(
$min-width: $min-width,
$mobile-breakpoint: $mobile-breakpoint,
$query: mdc-helpers.$mdc-base-styles-query
);

// The MDC `min-width` mixin has a similar breakpoint that sets `min-width: 100%` on the surface
// element to make it span the entire viewport, however it ends up collapsing because the
// container is `width: auto`. This query ensures that the surface will span the whole viewport.
@media (max-width: $mobile-breakpoint), (max-width: $min-width) {
@use '../core/style/elevation';

$_side-padding: 8px;

.mat-mdc-snack-bar-container {
@include elevation.elevation(6);
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
margin: 8px;
max-width: 672px;

.mat-mdc-snack-bar-handset & {
width: 100vw;
}

@include token-utils.use-tokens(
tokens-mdc-snack-bar.$prefix,
tokens-mdc-snack-bar.get-token-slots()
) {
@include token-utils.create-token-slot(border-radius, container-shape);
@include token-utils.create-token-slot(background-color, container-color);
@include token-utils.create-token-slot(background-color, container-color);
}
}

@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
// Include the styles without the animations since we
// reuse the same animation as the non-MDC version.
@include mdc-snackbar.static-styles($query: mdc-helpers.$mdc-base-styles-without-animation-query);

.mat-mdc-snack-bar-container {
@include _container-min-width;
@include mdc-snackbar-theme.max-width(
mdc-snackbar-theme.$max-width,
$query: mdc-helpers.$mdc-base-styles-query
);
@include mdc-snackbar-theme.viewport-margin(
mdc-snackbar-theme.$viewport-margin-narrow,
$query: mdc-helpers.$mdc-base-styles-query
);

// MDC has the `container-elevation` which sounds like it should work, but it ends up applying
// the shadow on the outer container instead of the `.mdc-snackbar__surface` which causes
// a white background behind the rounded corners, because the `border-radius` is on the
// surface element.
@include mdc-snackbar-theme.elevation(mdc-snackbar-theme.$elevation);
@include mdc-snackbar-theme.theme-styles(tokens-mdc-snack-bar.get-token-slots());

// MDC sets the position as fixed and sets the container on the bottom center of the page (or
// otherwise can be set to be "leading"). Our overlay handles a more advanced configuration
// of positions, so we'll defer logic there.
position: static;

// The `mat-mdc-button` and `:not(:disabled)` here are redundant, but we need them to increase
// the specificity over the button styles that may bleed in from the rest of the app.
.mat-mdc-button.mat-mdc-snack-bar-action:not(:disabled) {
// MDC's `action-label-text-color` should be able to do this, but the button theme has a
// higher specificity so it ends up overriding it. Define our own variable that we can
// use to control the color instead.
@include token-utils.use-tokens(
tokens-mat-snack-bar.$prefix,
tokens-mat-snack-bar.get-token-slots()
) {
@include token-utils.create-token-slot(color, button-color);
}

// Darken the ripples in the button so they're visible against the dark background.
@include token-utils.create-token-values(tokens-mat-text-button.$prefix, (
state-layer-color: currentColor,
ripple-color: currentColor,
));

.mat-ripple-element {
opacity: 0.1;
}
}
.mat-mdc-snackbar-surface {
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
padding-left: 0;
padding-right: $_side-padding;
min-width: 344px;
max-width: 100%;

[dir='rtl'] & {
padding-right: 0;
padding-left: $_side-padding;
}

// Ensures that the snack bar stretches to full width in handset mode.
.mat-mdc-snack-bar-handset & {
width: 100%;
min-width: 0;
}

@include cdk.high-contrast(active, off) {
outline: solid 1px;
}

// MDC uses this pseudo element to work around an issue with their live announcer, but it
// can cause additional space for long snack bar messages (see #26685). Since we don't use
// MDC's announcer, we can hide the element.
.mdc-snackbar__label::before {
display: none;
@include token-utils.use-tokens(
tokens-mdc-snack-bar.$prefix,
tokens-mdc-snack-bar.get-token-slots()
) {
.mat-mdc-snack-bar-container & {
@include token-utils.create-token-slot(color, supporting-text-color);
@include token-utils.create-token-slot(font-family, supporting-text-font);
@include token-utils.create-token-slot(font-size, supporting-text-size);
@include token-utils.create-token-slot(font-weight, supporting-text-weight);
@include token-utils.create-token-slot(line-height, supporting-text-line-height);
}
}
}

.mdc-snackbar__label {
width: 100%;
flex-grow: 1;
box-sizing: border-box;
margin: 0;
padding: 14px $_side-padding 14px 16px;

[dir='rtl'] & {
padding-left: $_side-padding;
padding-right: 16px;
}
}

.mat-mdc-snack-bar-actions {
display: flex;
flex-shrink: 0;
align-items: center;
box-sizing: border-box;
}

// These elements need to have full width using flex layout.
.mat-mdc-snack-bar-handset,
.mat-mdc-snack-bar-container,
Expand All @@ -96,7 +99,26 @@
flex: 1 1 auto;
}

// Ensures that the snack bar stretches to full width in handset mode.
.mat-mdc-snack-bar-handset .mdc-snackbar__surface {
width: 100%;
// The `mat-mdc-button` and `:not(:disabled)` here are redundant, but we need them to increase
// the specificity over the button styles that may bleed in from the rest of the app.
.mat-mdc-snack-bar-container .mat-mdc-button.mat-mdc-snack-bar-action:not(:disabled) {
// MDC's `action-label-text-color` should be able to do this, but the button theme has a
// higher specificity so it ends up overriding it. Define our own variable that we can
// use to control the color instead.
@include token-utils.use-tokens(
tokens-mat-snack-bar.$prefix,
tokens-mat-snack-bar.get-token-slots()
) {
@include token-utils.create-token-slot(color, button-color);
}

// Darken the ripples in the button so they're visible against the dark background.
@include token-utils.create-token-values(tokens-mat-text-button.$prefix, (
state-layer-color: currentColor,
ripple-color: currentColor,
));

.mat-ripple-element {
opacity: 0.1;
}
}
2 changes: 1 addition & 1 deletion src/material/snack-bar/snack-bar-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ let uniqueId = 0;
standalone: true,
imports: [CdkPortalOutlet],
host: {
'class': 'mdc-snackbar mat-mdc-snack-bar-container mdc-snackbar--open',
'class': 'mdc-snackbar mat-mdc-snack-bar-container',
'[@state]': '_animationState',
'(@state.done)': 'onAnimationEnd($event)',
},
Expand Down

0 comments on commit 5cc8c2c

Please sign in to comment.