Skip to content

Commit

Permalink
perf(material-experimental/mdc-list): reduce bundle size (#24291)
Browse files Browse the repository at this point in the history
Reduces the amount of CSS generated by the MDC-based list by:
* Uses a similar approach to #24256 to reduce the amount of CSS for the internal checkbox. These changes reduce the styles even more, because we can exclude the hover/focus/pressed styles. This shaved off ~15kb.
* Disabling CSS variable fallbacks. This shaved off another 1-2kb.
  • Loading branch information
crisbeto committed Jan 27, 2022
1 parent fed8fae commit 5a00027
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 77 deletions.
1 change: 1 addition & 0 deletions src/material-experimental/mdc-checkbox/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ sass_binary(
"external/npm/node_modules",
],
deps = [
":mdc_checkbox_scss_lib",
"//src/material-experimental/mdc-helpers:mdc_helpers_scss_lib",
"//src/material-experimental/mdc-helpers:mdc_scss_deps_lib",
"//src/material/core:core_scss_lib",
Expand Down
46 changes: 46 additions & 0 deletions src/material-experimental/mdc-checkbox/_checkbox-private.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@use 'sass:map';
@use 'sass:color';
@use '@material/checkbox/checkbox-theme' as mdc-checkbox-theme;
@use '@material/theme/theme-color' as mdc-theme-color;

// Configuration used to define the theme-related CSS variables.
$private-checkbox-theme-config: map.merge(mdc-checkbox-theme.$light-theme, (
// Exclude all of the ripple-related styles.
selected-focus-state-layer-color: null,
selected-focus-state-layer-opacity: null,
selected-hover-state-layer-color: null,
selected-hover-state-layer-opacity: null,
selected-pressed-state-layer-color: null,
selected-pressed-state-layer-opacity: null,
unselected-focus-state-layer-color: null,
unselected-focus-state-layer-opacity: null,
unselected-hover-state-layer-color: null,
unselected-hover-state-layer-opacity: null,
unselected-pressed-state-layer-color: null,
unselected-pressed-state-layer-opacity: null,
));

// Mixin that includes the checkbox theme styles with a given palette.
// By default, the MDC checkbox always uses the `secondary` palette.
@mixin private-checkbox-styles-with-color($color, $mdc-color) {
$on-surface: mdc-theme-color.prop-value(on-surface);
$border-color: rgba($on-surface, color.opacity(mdc-checkbox-theme.$border-color));
$disabled-color: rgba($on-surface, color.opacity(mdc-checkbox-theme.$disabled-color));

@include mdc-checkbox-theme.theme((
selected-checkmark-color: mdc-theme-color.prop-value(on-#{$mdc-color}),

selected-focus-icon-color: $color,
selected-hover-icon-color: $color,
selected-icon-color: $color,
selected-pressed-icon-color: $color,
unselected-focus-icon-color: $color,
unselected-hover-icon-color: $color,

disabled-selected-icon-color: $disabled-color,
disabled-unselected-icon-color: $disabled-color,

unselected-icon-color: $border-color,
unselected-pressed-icon-color: $border-color,
));
}
33 changes: 4 additions & 29 deletions src/material-experimental/mdc-checkbox/_checkbox-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,7 @@
@use '../../material/core/typography/typography';
@use '../../material/core/theming/theming';
@use '../../material/core/ripple/ripple-theme';


// Mixin that includes the checkbox theme styles with a given palette.
// By default, the MDC checkbox always uses the `secondary` palette.
@mixin private-checkbox-styles-with-color($color, $mdc-color) {
$on-surface: mdc-theme-color.prop-value(on-surface);
$border-color: rgba($on-surface, color.opacity(mdc-checkbox-theme.$border-color));
$disabled-color: rgba($on-surface, color.opacity(mdc-checkbox-theme.$disabled-color));

@include mdc-checkbox-theme.theme((
selected-checkmark-color: mdc-theme-color.prop-value(on-#{$mdc-color}),

selected-focus-icon-color: $color,
selected-hover-icon-color: $color,
selected-icon-color: $color,
selected-pressed-icon-color: $color,
unselected-focus-icon-color: $color,
unselected-hover-icon-color: $color,

disabled-selected-icon-color: $disabled-color,
disabled-unselected-icon-color: $disabled-color,

unselected-icon-color: $border-color,
unselected-pressed-icon-color: $border-color,
));
}
@use './checkbox-private';

// Apply ripple colors to the MatRipple element and the MDC ripple element when the
// checkbox is selected.
Expand Down Expand Up @@ -77,17 +52,17 @@
// class for accent and warn style, and applying the appropriate overrides below. Since we
// don't use MDC's ripple, we also need to set the color for our replacement ripple.
&.mat-primary {
@include private-checkbox-styles-with-color($primary, primary);
@include checkbox-private.private-checkbox-styles-with-color($primary, primary);
@include _selected-ripple-colors($primary, primary);
}

&.mat-accent {
@include private-checkbox-styles-with-color($accent, secondary);
@include checkbox-private.private-checkbox-styles-with-color($accent, secondary);
@include _selected-ripple-colors($accent, secondary);
}

&.mat-warn {
@include private-checkbox-styles-with-color($warn, error);
@include checkbox-private.private-checkbox-styles-with-color($warn, error);
@include _selected-ripple-colors($warn, error);
}
}
Expand Down
17 changes: 2 additions & 15 deletions src/material-experimental/mdc-checkbox/checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/style/layout-common';
@use '../../material/core/style/vendor-prefixes';
@use './checkbox-private';

@include mdc-helpers.disable-fallback-declarations {
@include mdc-checkbox.static-styles($query: mdc-helpers.$mat-base-styles-query);
Expand All @@ -30,21 +31,7 @@
// MDC theme styles also include structural styles so we have to include the theme at least
// once here. The values will be overwritten by our own theme file afterwards.
@include mdc-helpers.disable-fallback-declarations {
@include mdc-checkbox-theme.theme-styles(map.merge(mdc-checkbox-theme.$light-theme, (
// Exclude all of the ripple-related styles.
selected-focus-state-layer-color: null,
selected-focus-state-layer-opacity: null,
selected-hover-state-layer-color: null,
selected-hover-state-layer-opacity: null,
selected-pressed-state-layer-color: null,
selected-pressed-state-layer-opacity: null,
unselected-focus-state-layer-color: null,
unselected-focus-state-layer-opacity: null,
unselected-hover-state-layer-color: null,
unselected-hover-state-layer-opacity: null,
unselected-pressed-state-layer-color: null,
unselected-pressed-state-layer-opacity: null,
)));
@include mdc-checkbox-theme.theme-styles(checkbox-private.$private-checkbox-theme-config);
}

// The MDC checkbox styles related to the hover state are intertwined with the MDC ripple
Expand Down
6 changes: 3 additions & 3 deletions src/material-experimental/mdc-list/_list-option-theme.scss
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
@use '@material/checkbox' as mdc-checkbox;
@use '../mdc-checkbox/checkbox-theme';
@use '../mdc-checkbox/checkbox-private';
@use '../mdc-helpers/mdc-helpers';
@use './list-option-trailing-avatar-compat';

// Mixin that overrides the selected item and checkbox colors for list options. By
// default, the MDC list uses the `primary` color for list items. The MDC checkbox
// inside list options by default uses the `primary` color too.
@mixin private-list-option-color-override($color, $mdcColor) {
@mixin private-list-option-color-override($color, $mdc-color) {
& .mdc-list-item__start, & .mdc-list-item__end {
@include checkbox-theme.private-checkbox-styles-with-color($color, $mdcColor);
@include checkbox-private.private-checkbox-styles-with-color($color, $mdc-color);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@use '@material/density/functions' as density-functions;
@use '@material/list/evolution-mixins' as mdc-list;
@use '@material/list/evolution-variables' as mdc-list-variables;
@use '../mdc-helpers/mdc-helpers';

// For compatibility with the non-MDC selection list, we support avatars that are
// shown at the end of the list option. This is not supported by the MDC list as the
Expand All @@ -15,19 +16,21 @@
@mixin core-styles($query) {
$feat-structure: feature-targeting.create-target($query, structure);

.mat-mdc-list-option-with-trailing-avatar {
@include mdc-list.item-end-spacing(16px, $query: $query);
@include mdc-list.item-end-size(40px, $query: $query);
@include mdc-helpers.disable-fallback-declarations {
.mat-mdc-list-option-with-trailing-avatar {
@include mdc-list.item-end-spacing(16px, $query: $query);
@include mdc-list.item-end-size(40px, $query: $query);

&.mdc-list-item--with-two-lines {
.mdc-list-item__primary-text {
@include typography.text-baseline($top: 32px, $bottom: 20px, $query: $query);
&.mdc-list-item--with-two-lines {
.mdc-list-item__primary-text {
@include typography.text-baseline($top: 32px, $bottom: 20px, $query: $query);
}
}
}

.mdc-list-item__end {
@include feature-targeting.targets($feat-structure) {
border-radius: 50%;
.mdc-list-item__end {
@include feature-targeting.targets($feat-structure) {
border-radius: 50%;
}
}
}
}
Expand All @@ -46,8 +49,10 @@
$property-name: height,
);

.mat-mdc-list-option-with-trailing-avatar {
@include mdc-list.one-line-item-height($one-line-tall-height);
@include mdc-list.two-line-item-height($two-line-tall-height);
@include mdc-helpers.disable-fallback-declarations {
.mat-mdc-list-option-with-trailing-avatar {
@include mdc-list.one-line-item-height($one-line-tall-height);
@include mdc-list.two-line-item-height($two-line-tall-height);
}
}
}
21 changes: 11 additions & 10 deletions src/material-experimental/mdc-list/_list-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
$accent: theming.get-color-from-palette(map.get($config, accent));
$warn: theming.get-color-from-palette(map.get($config, warn));

// MDC's state styles are tied in with their ripple. Since we don't use the MDC
// ripple, we need to add the hover, focus and selected states manually.
@include interactive-list-theme.private-interactive-list-item-state-colors($config);

@include mdc-helpers.mat-using-mdc-theme($config) {
// MDC's state styles are tied in with their ripple. Since we don't use the MDC
// ripple, we need to add the hover, focus and selected states manually.
@include interactive-list-theme.private-interactive-list-item-state-colors($config);
@include mdc-list.without-ripple($query: mdc-helpers.$mat-theme-styles-query);

.mat-mdc-list-option {
Expand All @@ -38,13 +37,15 @@
@mixin density($config-or-theme) {
$density-scale: theming.get-density-config($config-or-theme);

.mat-mdc-list-item {
@include mdc-list.one-line-item-density($density-scale);
@include mdc-list.two-line-item-density($density-scale);
@include mdc-list.three-line-item-density($density-scale);
}
@include mdc-helpers.disable-fallback-declarations {
.mat-mdc-list-item {
@include mdc-list.one-line-item-density($density-scale);
@include mdc-list.two-line-item-density($density-scale);
@include mdc-list.three-line-item-density($density-scale);
}

@include list-option-theme.private-list-option-density-styles($density-scale);
@include list-option-theme.private-list-option-density-styles($density-scale);
}
}

@mixin typography($config-or-theme) {
Expand Down
26 changes: 20 additions & 6 deletions src/material-experimental/mdc-list/list-option.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
@use '@material/checkbox' as mdc-checkbox;
@use 'sass:map';
@use '@material/checkbox/checkbox' as mdc-checkbox;
@use '@material/list/evolution-variables' as mdc-list-variables;
@use '@material/checkbox/checkbox-theme' as mdc-checkbox-theme;
@use '../mdc-helpers/mdc-helpers';
@use '../../cdk/a11y';
@use './list-option-trailing-avatar-compat';
@use '../mdc-checkbox/checkbox-private';

// For compatibility with the non-MDC list, we support avatars that are shown at the end
// of the list option. We create a class similar to MDC's `--trailing-icon` one.
Expand All @@ -12,19 +14,31 @@
.mat-mdc-list-option {
// The MDC-based list-option uses the MDC checkbox for the selection indicators.
// We need to ensure that the checkbox styles are not included for the list-option.
@include mdc-checkbox.without-ripple(
$query: mdc-helpers.$mat-base-styles-without-animation-query);
@include mdc-helpers.disable-fallback-declarations {
@include mdc-checkbox.static-styles(
$query: mdc-helpers.$mat-base-styles-without-animation-query);

&:not(._mat-animation-noopable) {
@include mdc-checkbox.without-ripple($query: animation);
&:not(._mat-animation-noopable) {
@include mdc-checkbox.static-styles($query: animation);
}
}

// We can't use the MDC checkbox here directly, because this checkbox is purely
// decorative and including the MDC one will bring in unnecessary JS.
.mdc-checkbox {
$config: map.merge(checkbox-private.$private-checkbox-theme-config, (
// Since this checkbox isn't interactive, we can exclude the focus/hover/press styles.
selected-focus-icon-color: null,
selected-hover-icon-color: null,
selected-pressed-icon-color: null,
unselected-focus-icon-color: null,
unselected-hover-icon-color: null,
unselected-pressed-icon-color: null,
));

// MDC theme styles also include structural styles so we have to include the theme at least
// once here. The values will be overwritten by our own theme file afterwards.
@include mdc-checkbox-theme.theme-styles(mdc-checkbox-theme.$light-theme);
@include mdc-checkbox-theme.theme-styles($config);
}

// The internal checkbox is purely decorative, but because it's an `input`, the user can still
Expand Down
4 changes: 3 additions & 1 deletion src/material-experimental/mdc-list/list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
@use '../mdc-helpers/mdc-helpers';
@use '../../material/core/style/layout-common';

@include mdc-list.without-ripple($query: mdc-helpers.$mat-base-styles-query);
@include mdc-helpers.disable-fallback-declarations {
@include mdc-list.without-ripple($query: mdc-helpers.$mat-base-styles-query);
}

// MDC expects the list element to be a `<ul>`, since we use `<mat-list>` instead we need to
// explicitly set `display: block`
Expand Down

0 comments on commit 5a00027

Please sign in to comment.