From 8f882833c2de49acacf71059aacbb82cc655f09a Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 9 Aug 2023 12:30:27 -0400 Subject: [PATCH 1/6] refactor(material/button): switch to tokens theming API --- src/material/button/_button-theme.scss | 88 ++++++++++-------- src/material/button/button.scss | 23 +++-- .../core/tokens/m2/mdc/_button-filled.scss | 92 +++++++++++++++++++ .../tokens/tests/test-validate-tokens.scss | 7 +- 4 files changed, 166 insertions(+), 44 deletions(-) create mode 100644 src/material/core/tokens/m2/mdc/_button-filled.scss diff --git a/src/material/button/_button-theme.scss b/src/material/button/_button-theme.scss index f3385a051e92..8ab5f7c48c86 100644 --- a/src/material/button/_button-theme.scss +++ b/src/material/button/_button-theme.scss @@ -11,6 +11,12 @@ @use '../core/theming/theming'; @use '../core/theming/inspection'; @use '../core/typography/typography'; +@use '../core/tokens/m2/mdc/button-filled' as tokens-mdc-button-filled; + +@function on-color($theme, $palette) { + $is-dark: inspection.get-theme-type($theme) == dark; + @return if(mdc-helpers.variable-safe-contrast-tone($palette, $is-dark) == 'dark', #000, #fff); +} @mixin _button-variant($color) { @include mdc-button-text-theme.theme(( @@ -18,13 +24,6 @@ )); } -@mixin _unelevated-button-variant($foreground, $background) { - @include mdc-button-filled-theme.theme(( - container-color: $background, - label-text-color: $foreground, - )); -} - @mixin _raised-button-variant($foreground, $background) { @include mdc-button-protected-theme.theme(( container-color: $background, @@ -79,35 +78,6 @@ } } - .mat-mdc-unelevated-button { - &.mat-unthemed { - @include _unelevated-button-variant($on-surface, $surface); - } - - &.mat-primary { - @include _unelevated-button-variant($on-primary, $primary); - } - - &.mat-accent { - @include _unelevated-button-variant($on-secondary, $secondary); - } - - &.mat-warn { - @include _unelevated-button-variant($on-error, $error); - } - - @include button-theme-private.apply-disabled-style() { - @include mdc-button-filled-theme.theme(( - // We need to pass both the disabled and enabled values, because the enabled - // ones apply to anchors while the disabled ones are for buttons. - disabled-container-color: $disabled-container-color, - disabled-label-text-color: $disabled-ink-color, - container-color: $disabled-container-color, - label-text-color: $disabled-ink-color, - )); - } - } - .mat-mdc-raised-button { &.mat-unthemed { @include _raised-button-variant($on-surface, $surface); @@ -180,6 +150,52 @@ @include button-theme-private.ripple-theme-styles($theme, true); } } + + .mat-mdc-unelevated-button { + $surface: inspection.get-theme-color($theme, background, card); + $primary: inspection.get-theme-color($theme, primary); + $accent: inspection.get-theme-color($theme, accent); + $warn: inspection.get-theme-color($theme, warn); + + $on-surface: on-color($theme, $surface); + $on-primary: on-color($theme, $primary); + $on-accent: on-color($theme, $accent); + $on-warn: on-color($theme, $warn); + + $default-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $surface, $on-surface); + $primary-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $primary, $on-primary); + $accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $accent, $on-accent); + $warn-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $warn, $on-warn); + + &.mat-unthemed { + @include mdc-button-filled-theme.theme($default-color-tokens); + } + + &.mat-primary { + @include mdc-button-filled-theme.theme($primary-color-tokens); + } + + &.mat-accent { + @include mdc-button-filled-theme.theme($accent-color-tokens); + } + + &.mat-warn { + @include mdc-button-filled-theme.theme($warn-color-tokens); + } + + @include button-theme-private.apply-disabled-style() { + $is-dark: inspection.get-theme-type($theme) == dark; + $disabled-ink-color: rgba($on-surface, if($is-dark, 0.5, 0.38)); + $disabled-container-color: rgba($on-surface, 0.12); + + @include mdc-button-filled-theme.theme(( + disabled-container-color: $disabled-container-color, + disabled-label-text-color: $disabled-ink-color, + container-color: $disabled-container-color, + label-text-color: $disabled-ink-color, + )); + } + } } @mixin typography($theme) { diff --git a/src/material/button/button.scss b/src/material/button/button.scss index b8e6dd6609b4..78ae4355f19a 100644 --- a/src/material/button/button.scss +++ b/src/material/button/button.scss @@ -6,11 +6,13 @@ @use '@material/button/button-filled-theme' as mdc-button-filled-theme; @use '@material/button/button-protected-theme' as mdc-button-protected-theme; @use '@material/button/button-outlined-theme' as mdc-button-outlined-theme; +@use '@material/theme/custom-properties' as mdc-custom-properties; @use './button-base'; @use '../core/mdc-helpers/mdc-helpers'; @use '../core/style/private' as style-private; @use '../core/focus-indicators/private' as focus-indicators-private; +@use '../core/tokens/m2/mdc/button-filled' as tokens-mdc-button-filled; @include mdc-helpers.disable-mdc-fallback-declarations { @include mdc-button.static-styles-without-ripple($query: mdc-helpers.$mdc-base-styles-query); @@ -33,13 +35,6 @@ map.merge(mdc-button-text-theme.$light-theme, $override-keys)); } - .mat-mdc-unelevated-button { - @include mdc-button-filled-theme.theme-styles( - map.merge(map.merge(mdc-button-filled-theme.$light-theme, $override-keys), ( - container-color: transparent, - ))); - } - .mat-mdc-raised-button { @include mdc-button-protected-theme.theme-styles( map.merge(map.merge(mdc-button-protected-theme.$light-theme, $override-keys), ( @@ -53,6 +48,20 @@ } } +@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) { + // Note that we don't include a feature query, because this mixins declare + // all the "slots" for CSS variables that will be defined in the theme. + .mat-mdc-unelevated-button { + $mdc-button-filled-slots: tokens-mdc-button-filled.get-token-slots(); + + // Add the slots for MDC text button. + @include mdc-button-filled-theme.theme-styles($mdc-button-filled-slots); + + // Add default values for MDC text button tokens that aren't outputted by the theming API. + @include mdc-button-filled-theme.theme(tokens-mdc-button-filled.get-unthemable-tokens()); + } +} + .mat-mdc-button, .mat-mdc-unelevated-button, .mat-mdc-raised-button, diff --git a/src/material/core/tokens/m2/mdc/_button-filled.scss b/src/material/core/tokens/m2/mdc/_button-filled.scss new file mode 100644 index 000000000000..d444ebc66b58 --- /dev/null +++ b/src/material/core/tokens/m2/mdc/_button-filled.scss @@ -0,0 +1,92 @@ +@use '../../token-utils'; +@use '../../../mdc-helpers/mdc-helpers'; +@use '../../../style/sass-utils'; +@use '../../../theming/inspection'; + +// The prefix used to generate the fully qualified name for tokens in this file. +$prefix: (mdc, button-filled); + +// Tokens that can't be configured through Angular Material's current theming API, +// but may be in a future version of the theming API. +// +// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`. +// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in +// our CSS. +@function get-unthemable-tokens() { + @return ( + container-elevation: 0, + container-height: 36px, + container-shape: 4px, + disabled-container-elevation: 0, + focus-container-elevation: 0, + focus-state-layer-opacity: 0.24, + hover-container-elevation: 0, + hover-state-layer-opacity: 0.08, + keep-touch-target: false, + pressed-container-elevation: 0, + pressed-state-layer-opacity: 0.24, + + container-shadow-color: null, + focus-label-text-color: null, + hover-label-text-color: null, + label-text-font: null, + label-text-size: null, + label-text-tracking: null, + label-text-transform: null, + label-text-weight: null, + pressed-label-text-color: null, + with-icon-disabled-icon-color: null, + with-icon-focus-icon-color: null, + with-icon-hover-icon-color: null, + with-icon-icon-color: null, + with-icon-icon-size: null, + with-icon-pressed-icon-color: null + ); +} + +@function on-color($theme, $palette) { + @if ($palette) { + $is-dark: inspection.get-theme-type($theme) == dark; + @return if(mdc-helpers.variable-safe-contrast-tone($palette, $is-dark) == 'dark', #000, #fff); + } +} + +// Tokens that can be configured through Angular Material's color theming API. +@function get-color-tokens($theme, $color: null, $on-color: null) { + $is-dark: inspection.get-theme-type($theme) == dark; + $primary: inspection.get-theme-color($theme, primary); + $surface: inspection.get-theme-color($theme, background, card); + $on-primary: on-color($theme, $primary); + $on-surface: on-color($theme, $surface); + + @return ( + container-color: if($color, $color, transparent), + disabled-container-color: rgba($on-surface, 0.12), + disabled-label-text-color: rgba($on-surface, if($is-dark, 0.5, 0.38)), + focus-state-layer-color: $on-primary, + hover-state-layer-color: $on-primary, + label-text-color: if($on-color, $on-color, inherit), + pressed-state-layer-color: $on-primary + ); +} + +// Tokens that can be configured through Angular Material's typography theming API. +@function get-typography-tokens($theme) { + @return (); +} + +// Tokens that can be configured through Angular Material's density theming API. +@function get-density-tokens($theme) { + @return (); +} + +// Combines the tokens generated by the above functions into a single map with placeholder values. +// This is used to create token slots. +@function get-token-slots() { + @return sass-utils.deep-merge-all( + get-unthemable-tokens(), + get-color-tokens(token-utils.$placeholder-color-config), + get-typography-tokens(token-utils.$placeholder-typography-config), + get-density-tokens(token-utils.$placeholder-density-config) + ); +} diff --git a/src/material/core/tokens/tests/test-validate-tokens.scss b/src/material/core/tokens/tests/test-validate-tokens.scss index 32e85bbaaa4d..15213bbd8426 100644 --- a/src/material/core/tokens/tests/test-validate-tokens.scss +++ b/src/material/core/tokens/tests/test-validate-tokens.scss @@ -104,7 +104,7 @@ @include validate-slots( $component: 'm2.mdc.switch', $slots: tokens-mdc-switch.get-token-slots(), - $reference: mdc-switch-theme.$light-theme, + $reference: mdc-switch-theme.$light-theme ); @include validate-slots( $component: 'm2.mdc.tab-indicator', @@ -156,3 +156,8 @@ $slots: tokens-mdc-outlined-text-field.get-token-slots(), $reference: mdc-outlined-text-field-theme.$light-theme ); +@include validate-slots( + $component: 'm2.mdc.button-filled', + $slots: tokens-mdc-extended-fab.get-token-slots(), + $reference: mdc-extended-fab-theme.$extended-light-theme +); From 2b0c208711a905634d20e38719d33bf24dfb3710 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Tue, 12 Sep 2023 14:32:45 -0400 Subject: [PATCH 2/6] fixup! refactor(material/button): switch to tokens theming API --- src/material/core/tokens/m2/mdc/_button-filled.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/material/core/tokens/m2/mdc/_button-filled.scss b/src/material/core/tokens/m2/mdc/_button-filled.scss index d444ebc66b58..161ed9d2078b 100644 --- a/src/material/core/tokens/m2/mdc/_button-filled.scss +++ b/src/material/core/tokens/m2/mdc/_button-filled.scss @@ -19,7 +19,7 @@ $prefix: (mdc, button-filled); container-shape: 4px, disabled-container-elevation: 0, focus-container-elevation: 0, - focus-state-layer-opacity: 0.24, + focus-state-layer-opacity: 0.12, hover-container-elevation: 0, hover-state-layer-opacity: 0.08, keep-touch-target: false, From deddbefa0b9b42149fc52d4f04e4d95070897592 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Wed, 13 Sep 2023 23:06:46 -0400 Subject: [PATCH 3/6] fixup! refactor(material/button): switch to tokens theming API --- src/material/core/tokens/m2/mdc/_button-filled.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/material/core/tokens/m2/mdc/_button-filled.scss b/src/material/core/tokens/m2/mdc/_button-filled.scss index 161ed9d2078b..3a9994384bda 100644 --- a/src/material/core/tokens/m2/mdc/_button-filled.scss +++ b/src/material/core/tokens/m2/mdc/_button-filled.scss @@ -19,13 +19,13 @@ $prefix: (mdc, button-filled); container-shape: 4px, disabled-container-elevation: 0, focus-container-elevation: 0, - focus-state-layer-opacity: 0.12, hover-container-elevation: 0, - hover-state-layer-opacity: 0.08, keep-touch-target: false, pressed-container-elevation: 0, - pressed-state-layer-opacity: 0.24, + focus-state-layer-opacity: null, + hover-state-layer-opacity: null, + pressed-state-layer-opacity: null, container-shadow-color: null, focus-label-text-color: null, hover-label-text-color: null, From 9621ae084d868cc9fb6112e182007a8aa229d538 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Thu, 14 Sep 2023 20:30:55 -0400 Subject: [PATCH 4/6] fixup! refactor(material/button): switch to tokens theming API --- src/material/button/_button-theme.scss | 6 +++++- .../core/tokens/m2/mdc/_button-filled.scss | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/material/button/_button-theme.scss b/src/material/button/_button-theme.scss index 8ab5f7c48c86..5c5e2ccd644b 100644 --- a/src/material/button/_button-theme.scss +++ b/src/material/button/_button-theme.scss @@ -206,10 +206,14 @@ @mixin density($theme) { $density-scale: theming.clamp-density(inspection.get-theme-density($theme), -3); + + .mat-mdc-unelevated-button { + $density-tokens: tokens-mdc-button-filled.get-density-tokens($theme); + @include mdc-button-filled-theme.theme($density-tokens); + } .mat-mdc-button, .mat-mdc-raised-button, - .mat-mdc-unelevated-button, .mat-mdc-outlined-button { // Use `mat-mdc-button-base` to increase the specificity over the button's structural styles. &.mat-mdc-button-base { diff --git a/src/material/core/tokens/m2/mdc/_button-filled.scss b/src/material/core/tokens/m2/mdc/_button-filled.scss index 3a9994384bda..1294cf0ad920 100644 --- a/src/material/core/tokens/m2/mdc/_button-filled.scss +++ b/src/material/core/tokens/m2/mdc/_button-filled.scss @@ -1,7 +1,9 @@ +@use 'sass:map'; @use '../../token-utils'; @use '../../../mdc-helpers/mdc-helpers'; @use '../../../style/sass-utils'; @use '../../../theming/inspection'; +@use '../../../theming/theming'; // The prefix used to generate the fully qualified name for tokens in this file. $prefix: (mdc, button-filled); @@ -15,7 +17,6 @@ $prefix: (mdc, button-filled); @function get-unthemable-tokens() { @return ( container-elevation: 0, - container-height: 36px, container-shape: 4px, disabled-container-elevation: 0, focus-container-elevation: 0, @@ -77,7 +78,20 @@ $prefix: (mdc, button-filled); // Tokens that can be configured through Angular Material's density theming API. @function get-density-tokens($theme) { - @return (); + $scale: theming.clamp-density(inspection.get-theme-density($theme), -3); + + @return ( + container-height: + map.get( + ( + 0: 36px, + -1: 32px, + -2: 28px, + -3: 24px, + ), + $scale + ) + ); } // Combines the tokens generated by the above functions into a single map with placeholder values. From 1638385751cec1403db0c893de914876b982314e Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Thu, 14 Sep 2023 22:19:53 -0400 Subject: [PATCH 5/6] fixup! refactor(material/button): switch to tokens theming API --- src/material/button/_button-theme.scss | 18 +++++++----------- .../core/tokens/m2/mdc/_button-filled.scss | 18 ++---------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/material/button/_button-theme.scss b/src/material/button/_button-theme.scss index 5c5e2ccd644b..def2c9d2278e 100644 --- a/src/material/button/_button-theme.scss +++ b/src/material/button/_button-theme.scss @@ -154,18 +154,18 @@ .mat-mdc-unelevated-button { $surface: inspection.get-theme-color($theme, background, card); $primary: inspection.get-theme-color($theme, primary); - $accent: inspection.get-theme-color($theme, accent); - $warn: inspection.get-theme-color($theme, warn); + $secondary: inspection.get-theme-color($theme, accent); + $error: inspection.get-theme-color($theme, warn); $on-surface: on-color($theme, $surface); $on-primary: on-color($theme, $primary); - $on-accent: on-color($theme, $accent); - $on-warn: on-color($theme, $warn); + $on-secondary: on-color($theme, $secondary); + $on-error: on-color($theme, $error); $default-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $surface, $on-surface); $primary-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $primary, $on-primary); - $accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $accent, $on-accent); - $warn-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $warn, $on-warn); + $accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $secondary, $on-secondary); + $warn-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $error, $on-error); &.mat-unthemed { @include mdc-button-filled-theme.theme($default-color-tokens); @@ -206,14 +206,10 @@ @mixin density($theme) { $density-scale: theming.clamp-density(inspection.get-theme-density($theme), -3); - - .mat-mdc-unelevated-button { - $density-tokens: tokens-mdc-button-filled.get-density-tokens($theme); - @include mdc-button-filled-theme.theme($density-tokens); - } .mat-mdc-button, .mat-mdc-raised-button, + .mat-mdc-unelevated-button, .mat-mdc-outlined-button { // Use `mat-mdc-button-base` to increase the specificity over the button's structural styles. &.mat-mdc-button-base { diff --git a/src/material/core/tokens/m2/mdc/_button-filled.scss b/src/material/core/tokens/m2/mdc/_button-filled.scss index 1294cf0ad920..3a9994384bda 100644 --- a/src/material/core/tokens/m2/mdc/_button-filled.scss +++ b/src/material/core/tokens/m2/mdc/_button-filled.scss @@ -1,9 +1,7 @@ -@use 'sass:map'; @use '../../token-utils'; @use '../../../mdc-helpers/mdc-helpers'; @use '../../../style/sass-utils'; @use '../../../theming/inspection'; -@use '../../../theming/theming'; // The prefix used to generate the fully qualified name for tokens in this file. $prefix: (mdc, button-filled); @@ -17,6 +15,7 @@ $prefix: (mdc, button-filled); @function get-unthemable-tokens() { @return ( container-elevation: 0, + container-height: 36px, container-shape: 4px, disabled-container-elevation: 0, focus-container-elevation: 0, @@ -78,20 +77,7 @@ $prefix: (mdc, button-filled); // Tokens that can be configured through Angular Material's density theming API. @function get-density-tokens($theme) { - $scale: theming.clamp-density(inspection.get-theme-density($theme), -3); - - @return ( - container-height: - map.get( - ( - 0: 36px, - -1: 32px, - -2: 28px, - -3: 24px, - ), - $scale - ) - ); + @return (); } // Combines the tokens generated by the above functions into a single map with placeholder values. From 0e81dd1356c57931f07108c14f9e21acd413f975 Mon Sep 17 00:00:00 2001 From: Wagner Maciel Date: Fri, 15 Sep 2023 11:09:29 -0400 Subject: [PATCH 6/6] fixup! refactor(material/button): switch to tokens theming API --- src/material/button/_button-theme.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/material/button/_button-theme.scss b/src/material/button/_button-theme.scss index def2c9d2278e..663fb39e7dc1 100644 --- a/src/material/button/_button-theme.scss +++ b/src/material/button/_button-theme.scss @@ -154,17 +154,17 @@ .mat-mdc-unelevated-button { $surface: inspection.get-theme-color($theme, background, card); $primary: inspection.get-theme-color($theme, primary); - $secondary: inspection.get-theme-color($theme, accent); + $accent: inspection.get-theme-color($theme, accent); $error: inspection.get-theme-color($theme, warn); $on-surface: on-color($theme, $surface); $on-primary: on-color($theme, $primary); - $on-secondary: on-color($theme, $secondary); + $on-accent: on-color($theme, $accent); $on-error: on-color($theme, $error); $default-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $surface, $on-surface); $primary-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $primary, $on-primary); - $accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $secondary, $on-secondary); + $accent-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $accent, $on-accent); $warn-color-tokens: tokens-mdc-button-filled.get-color-tokens($theme, $error, $on-error); &.mat-unthemed {