From 963d6d1345a746b7a124bf0aa064af153395fcb8 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 27 Jan 2022 10:28:06 +0100 Subject: [PATCH] perf(material-experimental/mdc-list): reduce bundle size 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. --- .../mdc-checkbox/BUILD.bazel | 1 + .../mdc-checkbox/_checkbox-private.scss | 46 +++++++++++++++++++ .../mdc-checkbox/_checkbox-theme.scss | 33 ++----------- .../mdc-checkbox/checkbox.scss | 17 +------ .../mdc-list/_list-option-theme.scss | 6 +-- .../_list-option-trailing-avatar-compat.scss | 31 +++++++------ .../mdc-list/_list-theme.scss | 21 +++++---- .../mdc-list/list-option.scss | 26 ++++++++--- src/material-experimental/mdc-list/list.scss | 4 +- 9 files changed, 108 insertions(+), 77 deletions(-) create mode 100644 src/material-experimental/mdc-checkbox/_checkbox-private.scss diff --git a/src/material-experimental/mdc-checkbox/BUILD.bazel b/src/material-experimental/mdc-checkbox/BUILD.bazel index 212185b79367..c5fa71155f34 100644 --- a/src/material-experimental/mdc-checkbox/BUILD.bazel +++ b/src/material-experimental/mdc-checkbox/BUILD.bazel @@ -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", diff --git a/src/material-experimental/mdc-checkbox/_checkbox-private.scss b/src/material-experimental/mdc-checkbox/_checkbox-private.scss new file mode 100644 index 000000000000..0a46f6a2a62c --- /dev/null +++ b/src/material-experimental/mdc-checkbox/_checkbox-private.scss @@ -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, + )); +} diff --git a/src/material-experimental/mdc-checkbox/_checkbox-theme.scss b/src/material-experimental/mdc-checkbox/_checkbox-theme.scss index d5a8cd8999bd..d520043ca765 100644 --- a/src/material-experimental/mdc-checkbox/_checkbox-theme.scss +++ b/src/material-experimental/mdc-checkbox/_checkbox-theme.scss @@ -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. @@ -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); } } diff --git a/src/material-experimental/mdc-checkbox/checkbox.scss b/src/material-experimental/mdc-checkbox/checkbox.scss index e4f217c44e91..4f0dea347280 100644 --- a/src/material-experimental/mdc-checkbox/checkbox.scss +++ b/src/material-experimental/mdc-checkbox/checkbox.scss @@ -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); @@ -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 diff --git a/src/material-experimental/mdc-list/_list-option-theme.scss b/src/material-experimental/mdc-list/_list-option-theme.scss index cef9b98d85fc..7a6ccdcee09f 100644 --- a/src/material-experimental/mdc-list/_list-option-theme.scss +++ b/src/material-experimental/mdc-list/_list-option-theme.scss @@ -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); } } diff --git a/src/material-experimental/mdc-list/_list-option-trailing-avatar-compat.scss b/src/material-experimental/mdc-list/_list-option-trailing-avatar-compat.scss index 24c84560b408..1a26a351bb0c 100644 --- a/src/material-experimental/mdc-list/_list-option-trailing-avatar-compat.scss +++ b/src/material-experimental/mdc-list/_list-option-trailing-avatar-compat.scss @@ -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 @@ -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%; + } } } } @@ -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); + } } } diff --git a/src/material-experimental/mdc-list/_list-theme.scss b/src/material-experimental/mdc-list/_list-theme.scss index b8d6048d8650..95469ff47000 100644 --- a/src/material-experimental/mdc-list/_list-theme.scss +++ b/src/material-experimental/mdc-list/_list-theme.scss @@ -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 { @@ -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) { diff --git a/src/material-experimental/mdc-list/list-option.scss b/src/material-experimental/mdc-list/list-option.scss index 1a3f93841125..351a92dc04fa 100644 --- a/src/material-experimental/mdc-list/list-option.scss +++ b/src/material-experimental/mdc-list/list-option.scss @@ -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. @@ -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 diff --git a/src/material-experimental/mdc-list/list.scss b/src/material-experimental/mdc-list/list.scss index e4894d5f2077..c31bf6888ce9 100644 --- a/src/material-experimental/mdc-list/list.scss +++ b/src/material-experimental/mdc-list/list.scss @@ -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 `