Skip to content

Commit

Permalink
fix(multiple): derive all token values from theme
Browse files Browse the repository at this point in the history
During the transition to tokens, we ended up with a bunch of places with hardcoded values in the form of `if($is-dark, #fff, #000)`. This is problematic for custom palettes, because the value is always hardcoded.

These changes attempt to derive the same values from the palette directly.

Fixes angular#26056.
  • Loading branch information
crisbeto committed Feb 29, 2024
1 parent f6e8584 commit 0e09c25
Show file tree
Hide file tree
Showing 25 changed files with 135 additions and 154 deletions.
4 changes: 2 additions & 2 deletions src/material/core/theming/_inspection.scss
Expand Up @@ -75,8 +75,8 @@ $_typography-properties: (font, font-family, line-height, font-size, letter-spac
@function get-theme-color($theme, $args...) {
$version: get-theme-version($theme);
$args-count: list.length($args);
@if $args-count != 1 and $args-count != 2 {
@error #{'Expected 2 or 3 arguments. Got:'} $args-count + 1;
@if $args-count != 1 and $args-count != 2 and $args-count != 3 {
@error #{'Expected between 2 and 4 arguments. Got:'} $args-count + 1;
}

@if $version == 0 {
Expand Down
Expand Up @@ -328,7 +328,7 @@ describe('theming inspection api', () => {
color: mat.get-theme-color($theme);
}
`),
).toThrowError(/Expected 2 or 3 arguments. Got: 1/);
).toThrowError(/Expected between 2 and 4 arguments\. Got: 1/);
});

it('should get typography properties from theme', () => {
Expand Down
3 changes: 3 additions & 0 deletions src/material/core/tokens/_token-utils.scss
Expand Up @@ -9,6 +9,9 @@
@use '../theming/theming';
@use '../typography/typography';

// Indicates whether we're building internally. Used for backwards compatibility.
$private-is-internal-build: false;

$_placeholder-color-palette: theming.define-palette(palette.$red-palette);

// Placeholder color config that can be passed to token getter functions when generating token
Expand Down
3 changes: 1 addition & 2 deletions src/material/core/tokens/m2/mat/_datepicker.scss
Expand Up @@ -50,7 +50,6 @@ $private-default-overlap-color: #a8dab5;
$preview-outline-color: $divider-color;
$today-disabled-outline-color: null;
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);

$primary-color: inspection.get-theme-color($theme, primary);
$range-tokens: get-range-color-tokens(private-get-range-background-color($primary-color));
Expand All @@ -75,7 +74,7 @@ $private-default-overlap-color: #a8dab5;
@return sass-utils.merge-all($calendar-tokens, $toggle-tokens, $range-tokens, (
toggle-icon-color: $inactive-icon-color,
calendar-body-label-text-color: $secondary-text-color,
calendar-period-button-text-color: $on-surface,
calendar-period-button-text-color: inspection.get-theme-color($theme, foreground, text, 1),
calendar-period-button-icon-color: $inactive-icon-color,
calendar-navigation-button-icon-color: $inactive-icon-color,
calendar-header-divider-color: $divider-color,
Expand Down
25 changes: 10 additions & 15 deletions src/material/core/tokens/m2/mat/_fab-small.scss
Expand Up @@ -4,7 +4,6 @@
@use '../../../theming/theming';
@use '../../../theming/inspection';
@use '../../../style/sass-utils';
@use '../../../mdc-helpers/mdc-helpers';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mat, fab-small);
Expand All @@ -18,7 +17,6 @@ $prefix: (mat, fab-small);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
Expand All @@ -29,13 +27,13 @@ $prefix: (mat, fab-small);
foreground-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand All @@ -48,24 +46,21 @@ $prefix: (mat, fab-small);

// MDC doesn't have tokens for disabled FABs so we need to implemented them ourselves.
// Background color of the container when the FAB is disabled.
disabled-state-container-color: rgba($on-surface, 0.12),
disabled-state-container-color: inspection.get-theme-color($theme, background, disabled-button,
0.12),

// Color of the icons and projected text when the FAB is disabled.
disabled-state-foreground-color: rgba($on-surface, if($is-dark, 0.5, 0.38)),
disabled-state-foreground-color: inspection.get-theme-color($theme, foreground, disabled-button,
if($is-dark, 0.5, 0.38)),
);
}

// Generates the mapping for the properties that change based on the FAB palette color.
@function private-get-color-palette-color-tokens($theme, $palette-name) {
$is-dark: inspection.get-theme-type($theme) == dark;
$container-color: inspection.get-theme-color($theme, $palette-name);
$contrast-tone: mdc-helpers.variable-safe-contrast-tone($container-color, $is-dark);
$color: if($contrast-tone == 'dark', #000, #fff);

@return (
foreground-color: $color,
state-layer-color: $color,
ripple-color: rgba($color, 0.1),
foreground-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1),
);
}

Expand Down
25 changes: 10 additions & 15 deletions src/material/core/tokens/m2/mat/_fab.scss
Expand Up @@ -4,7 +4,6 @@
@use '../../../theming/theming';
@use '../../../theming/inspection';
@use '../../../style/sass-utils';
@use '../../../mdc-helpers/mdc-helpers';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mat, fab);
Expand All @@ -18,7 +17,6 @@ $prefix: (mat, fab);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
Expand All @@ -29,13 +27,13 @@ $prefix: (mat, fab);
foreground-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand All @@ -48,24 +46,21 @@ $prefix: (mat, fab);

// MDC doesn't have tokens for disabled FABs so we need to implemented them ourselves.
// Background color of the container when the FAB is disabled.
disabled-state-container-color: rgba($on-surface, 0.12),
disabled-state-container-color: inspection.get-theme-color($theme, background, disabled-button,
0.12),

// Color of the icons and projected text when the FAB is disabled.
disabled-state-foreground-color: rgba($on-surface, if($is-dark, 0.5, 0.38)),
disabled-state-foreground-color: inspection.get-theme-color($theme, foreground, disabled-button,
if($is-dark, 0.5, 0.38)),
);
}

// Generates the mapping for the properties that change based on the FAB palette color.
@function private-get-color-palette-color-tokens($theme, $palette-name) {
$is-dark: inspection.get-theme-type($theme) == dark;
$container-color: inspection.get-theme-color($theme, $palette-name);
$contrast-tone: mdc-helpers.variable-safe-contrast-tone($container-color, $is-dark);
$color: if($contrast-tone == 'dark', #000, #fff);

@return (
foreground-color: $color,
state-layer-color: $color,
ripple-color: rgba($color, 0.1),
foreground-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1),
);
}

Expand Down
17 changes: 5 additions & 12 deletions src/material/core/tokens/m2/mat/_filled-button.scss
Expand Up @@ -4,7 +4,6 @@
@use '../../../theming/theming';
@use '../../../theming/inspection';
@use '../../../style/sass-utils';
@use '../../../mdc-helpers/mdc-helpers';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mat, filled-button);
Expand All @@ -28,21 +27,20 @@ $prefix: (mat, filled-button);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
);

@return (
// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand All @@ -57,14 +55,9 @@ $prefix: (mat, filled-button);

// Generates the mapping for the properties that change based on the button palette color.
@function private-get-color-palette-color-tokens($theme, $palette-name) {
$is-dark: inspection.get-theme-type($theme) == dark;
$container-color: inspection.get-theme-color($theme, $palette-name);
$contrast-tone: mdc-helpers.variable-safe-contrast-tone($container-color, $is-dark);
$color: if($contrast-tone == 'dark', #000, #fff);

@return (
state-layer-color: $color,
ripple-color: rgba($color, 0.1),
state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1),
);
}

Expand Down
10 changes: 5 additions & 5 deletions src/material/core/tokens/m2/mat/_form-field.scss
Expand Up @@ -20,13 +20,13 @@ $prefix: (mat, form-field);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$color-tokens: private-get-color-palette-color-tokens($theme, primary);

@return map.merge($color-tokens, (
// MDC has a token for the enabled placeholder, but not for the disabled one.
disabled-input-text-placeholder-color: rgba($on-surface, 0.38),
state-layer-color: rgba($on-surface, 0.87),
disabled-input-text-placeholder-color:
inspection.get-theme-color($theme, foreground, icon, 0.38),
state-layer-color: inspection.get-theme-color($theme, foreground, base, 0.87),
error-text-color: inspection.get-theme-color($theme, warn),

// On dark themes we set the native `select` color to some shade of white,
Expand Down Expand Up @@ -56,8 +56,8 @@ $prefix: (mat, form-field);

// These values are taken from the MDC select implementation:
// https://github.com/material-components/material-components-web/blob/master/packages/mdc-select/_select-theme.scss
enabled-select-arrow-color: rgba($on-surface, 0.54),
disabled-select-arrow-color: rgba($on-surface, 0.38),
enabled-select-arrow-color: inspection.get-theme-color($theme, foreground, icon, 0.54),
disabled-select-arrow-color: inspection.get-theme-color($theme, foreground, icon, 0.38),

hover-state-layer-opacity: if($is-dark, 0.08, 0.04),
focus-state-layer-opacity: if($is-dark, 0.24, 0.08),
Expand Down
7 changes: 3 additions & 4 deletions src/material/core/tokens/m2/mat/_icon-button.scss
Expand Up @@ -18,21 +18,20 @@ $prefix: (mat, icon-button);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
);

@return (
// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand Down
4 changes: 2 additions & 2 deletions src/material/core/tokens/m2/mat/_menu.scss
Expand Up @@ -24,8 +24,8 @@ $prefix: (mat, menu);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$active-state-layer-color: rgba($on-surface, if($is-dark, 0.08, 0.04));
$active-state-layer-color: inspection.get-theme-color($theme, foreground, base,
if($is-dark, 0.08, 0.04));
$text-color: inspection.get-theme-color($theme, foreground, text);

@return (
Expand Down
4 changes: 2 additions & 2 deletions src/material/core/tokens/m2/mat/_option.scss
Expand Up @@ -15,8 +15,8 @@ $prefix: (mat, option);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme, $palette-name: primary) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$active-state-layer-color: rgba($on-surface, if($is-dark, 0.08, 0.04));
$active-state-layer-color: inspection.get-theme-color($theme, foreground, base,
if($is-dark, 0.08, 0.04));

@return (
selected-state-label-text-color: inspection.get-theme-color($theme, $palette-name),
Expand Down
7 changes: 3 additions & 4 deletions src/material/core/tokens/m2/mat/_outlined-button.scss
Expand Up @@ -28,21 +28,20 @@ $prefix: (mat, outlined-button);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
);

@return (
// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand Down
17 changes: 5 additions & 12 deletions src/material/core/tokens/m2/mat/_protected-button.scss
Expand Up @@ -4,7 +4,6 @@
@use '../../../theming/theming';
@use '../../../theming/inspection';
@use '../../../style/sass-utils';
@use '../../../mdc-helpers/mdc-helpers';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mat, protected-button);
Expand All @@ -28,21 +27,20 @@ $prefix: (mat, protected-button);
// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme) {
$is-dark: inspection.get-theme-type($theme) == dark;
$on-surface: if($is-dark, #fff, #000);
$ripple-opacities: if($is-dark,
mdc-ripple-theme.$light-ink-opacities,
mdc-ripple-theme.$dark-ink-opacities
);

@return (
// Color of the element that shows the hover, focus and pressed states.
state-layer-color: $on-surface,
state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the element that shows the hover, focus and pressed states while disabled.
disabled-state-layer-color: $on-surface,
disabled-state-layer-color: inspection.get-theme-color($theme, foreground, base),

// Color of the ripple element.
ripple-color: rgba($on-surface, 0.1),
ripple-color: inspection.get-theme-color($theme, foreground, base, 0.1),

// Opacity of the ripple when the button is hovered.
hover-state-layer-opacity: map.get($ripple-opacities, hover),
Expand All @@ -57,14 +55,9 @@ $prefix: (mat, protected-button);

// Generates the mapping for the properties that change based on the button palette color.
@function private-get-color-palette-color-tokens($theme, $palette-name) {
$is-dark: inspection.get-theme-type($theme) == dark;
$container-color: inspection.get-theme-color($theme, $palette-name);
$contrast-tone: mdc-helpers.variable-safe-contrast-tone($container-color, $is-dark);
$color: if($contrast-tone == 'dark', #000, #fff);

@return (
state-layer-color: $color,
ripple-color: rgba($color, 0.1),
state-layer-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 1),
ripple-color: inspection.get-theme-color($theme, $palette-name, default-contrast, 0.1),
);
}

Expand Down
4 changes: 1 addition & 3 deletions src/material/core/tokens/m2/mat/_radio.scss
Expand Up @@ -14,10 +14,8 @@ $prefix: (mat, radio);

// Tokens that can be configured through Angular Material's color theming API.
@function get-color-tokens($theme, $palette-name: accent) {
$is-dark: inspection.get-theme-type($theme) == dark;

@return (
ripple-color: if($is-dark, #fff, #000),
ripple-color: inspection.get-theme-color($theme, foreground, base),
checked-ripple-color: inspection.get-theme-color($theme, $palette-name, default),
disabled-label-color: inspection.get-theme-color($theme, foreground, disabled-text),
);
Expand Down

0 comments on commit 0e09c25

Please sign in to comment.