diff --git a/src/material/core/tokens/m2/mat/_icon.scss b/src/material/core/tokens/m2/mat/_icon.scss new file mode 100644 index 000000000000..e7d4e1489e39 --- /dev/null +++ b/src/material/core/tokens/m2/mat/_icon.scss @@ -0,0 +1,45 @@ +@use '../../token-utils'; +@use '../../../style/sass-utils'; + +// The prefix used to generate the fully qualified name for tokens in this file. +$prefix: (mat, icon); + +// Tokens that can't be configured through Angular Material's current theming API, +// but may be in a future version of the theming API. +@function get-unthemable-tokens() { + @return (); +} + +// Tokens that can be configured through Angular Material's color theming API. +@function get-color-tokens($config) { + // Default the icon to `inherit` so it matches the text around it. + @return private-get-icon-color-tokens(inherit); +} + +// Tokens that can be configured through Angular Material's typography theming API. +@function get-typography-tokens($config) { + @return (); +} + +// Tokens that can be configured through Angular Material's density theming API. +@function get-density-tokens($config) { + @return (); +} + +// Mixin used to set a specific color on an icon. +@function private-get-icon-color-tokens($color) { + @return ( + color: $color, + ); +} + +// 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/icon/_icon-theme.scss b/src/material/icon/_icon-theme.scss index a938200d4995..1daac623b3fc 100644 --- a/src/material/icon/_icon-theme.scss +++ b/src/material/icon/_icon-theme.scss @@ -1,25 +1,35 @@ @use 'sass:map'; @use '../core/theming/theming'; +@use '../core/tokens/m2/mat/icon' as tokens-mat-icon; +@use '../core/tokens/token-utils'; +@use '../core/style/sass-utils'; + +@mixin _palette-colors($config, $palette-name) { + $palette: map.get($config, $palette-name); + $color: theming.get-color-from-palette($palette, text); + $tokens: tokens-mat-icon.private-get-icon-color-tokens($color); + @include token-utils.create-token-values(tokens-mat-icon.$prefix, $tokens); +} @mixin color($config-or-theme) { $config: theming.get-color-config($config-or-theme); - $primary: map.get($config, primary); - $accent: map.get($config, accent); - $warn: map.get($config, warn); - $background: map.get($config, background); - $foreground: map.get($config, foreground); + + @include sass-utils.current-selector-or-root() { + @include token-utils.create-token-values(tokens-mat-icon.$prefix, + tokens-mat-icon.get-color-tokens($config)); + } .mat-icon { &.mat-primary { - color: theming.get-color-from-palette($primary, text); + @include _palette-colors($config, primary); } &.mat-accent { - color: theming.get-color-from-palette($accent, text); + @include _palette-colors($config, accent); } &.mat-warn { - color: theming.get-color-from-palette($warn, text); + @include _palette-colors($config, warn); } } } diff --git a/src/material/icon/icon.scss b/src/material/icon/icon.scss index 09f2889207ad..bddac57f92e0 100644 --- a/src/material/icon/icon.scss +++ b/src/material/icon/icon.scss @@ -1,8 +1,26 @@ @use '../core/style/vendor-prefixes'; +@use '../core/tokens/m2/mat/icon' as tokens-mat-icon; +@use '../core/tokens/token-utils'; // The width/height of the icon element. $size: 24px !default; +// Note that here we target the `mat-icon` tag name with the `color`, instead of `.mat-icon` to +// avoid breaking any existing overrides. It's common to customize the color of icons by setting a +// `color` on the root node. This was easy before the tokens API, because `.mat-icon` doesn't have +// any `color` and users could easily specify it. By adding support for tokens, we have to set a +// `color` so the CSS variable declaration works, but by doing so we can break existing overrides. +// We mitigate against it by targeting the tag name which has the lowest possible specificity. +// Note that this means that we also have to re-declare the property for `primary`, `accent` and +// `warn` because there we want the additional specificity. +mat-icon { + &, &.mat-primary, &.mat-accent, &.mat-warn { + @include token-utils.use-tokens(tokens-mat-icon.$prefix, tokens-mat-icon.get-token-slots()) { + @include token-utils.create-token-slot(color, color); + } + } +} + .mat-icon { @include vendor-prefixes.user-select(none); background-repeat: no-repeat;