Skip to content

Commit

Permalink
refactor(material/core): split up M3 token processing into separate f…
Browse files Browse the repository at this point in the history
…iles

Splits up our processing of MDC's tokens into separate files so they're a bit more manageable.
  • Loading branch information
crisbeto committed Apr 29, 2024
1 parent 5e98b0d commit f245153
Show file tree
Hide file tree
Showing 30 changed files with 1,384 additions and 1,236 deletions.
605 changes: 0 additions & 605 deletions src/material/core/tokens/_custom-tokens.scss

This file was deleted.

605 changes: 0 additions & 605 deletions src/material/core/tokens/_m3-tokens.scss

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions src/material/core/tokens/_token-utils.scss
Expand Up @@ -5,6 +5,7 @@
@use '@material/theme/custom-properties' as mdc-custom-properties;
@use '@material/theme/theme' as mdc-theme;
@use '@material/theme/keys' as mdc-keys;
@use '@material/tokens/v0_161' as mdc-tokens;
@use '../style/sass-utils';
@use '../m2/palette' as m2-palette;
@use '../m2/theming' as m2-theming;
Expand Down Expand Up @@ -142,6 +143,17 @@ $_component-prefix: null;
}
}

/// Gets all the MDC token values for a specific component. This function serves as single
/// point at which we directly reference a specific version of the MDC tokens.
/// @param {String} $component Name of the component for which to get the tokens
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
/// @return {List} Map of token names to values
@function get-mdc-tokens($component, $systems, $exclude-hardcoded) {
$fn: meta.get-function($name: 'md-comp-' + $component + '-values', $module: 'mdc-tokens');
@return meta.call($fn, $systems, $exclude-hardcoded);
}

// MDC doesn't currently handle elevation tokens properly. As a temporary workaround we can combine
// the elevation and shadow-color tokens into a full box-shadow and use it as the value for the
// elevation token.
Expand Down Expand Up @@ -288,6 +300,63 @@ $_component-prefix: null;
@return $result;
}

/// Maps the values in a map to new values using the given mapping function
/// @param {Map} $map The maps whose values will be mapped to new values.
/// @param {Function} $fn The value mapping function.
/// @param {Map} A new map with its values updated using the mapping function.
@function map-values($map, $fn) {
$result: ();
@each $key, $value in $map {
$result: map.set($result, $key, meta.call($fn, $value));
}
@return $result;
}

/// Renames the keys in a map
/// @param {Map} $map The map whose keys should be renamed
/// @param {Map} $rename-keys A map of original key to renamed key to apply to $map
/// @return {Map} The result of applying the given key renames to the given map.
@function rename-map-keys($map, $rename-keys) {
$result: $map;
@each $old-key-name, $new-key-name in $rename-keys {
@if map.has-key($map, $old-key-name) {
$result: map.set($result, $new-key-name, map.get($map, $old-key-name));
}
}
@return $result;
}

/// At the time of writing, some color tokens (e.g. disabled state) are defined as a solid color
/// token and a separate opacity token. This function applies the opacity to the color and drops the
/// opacity key from the map. Can be removed once b/213331407 is resolved.
/// @param {Map} $tokens The map of tokens currently being generated
/// @param {Map} $all-tokens A map of all tokens, including hardcoded values
/// @param {List} $pairs Pairs of color token names and their opacities. Should be in the shape of
/// `((color: 'color-key', opacity: 'opacity-key'))`.
/// @return {Map} The initial tokens with the combined color values.
@function combine-color-tokens($tokens, $opacity-lookup, $pairs) {
$result: $tokens;

@each $pair in $pairs {
$color-key: map.get($pair, color);
$opacity-key: map.get($pair, opacity);
$color: map.get($tokens, $color-key);
$opacity: map.get($opacity-lookup, $opacity-key);

@if(meta.type-of($color) == 'color') {
$result: map.remove($result, $opacity-key);
$result: map.set($result, $color-key, rgba($color, $opacity));
}
@else if($color != null) {
$result: map.remove($result, $opacity-key);
$combined-color: #{color-mix(in srgb, #{$color} #{($opacity * 100) + '%'}, transparent)};
$result: map.set($result, $color-key, $combined-color);
}
}

@return $result;
}

/// Verifies that the token overrides exist and are used in one of the given token maps.
@mixin _validate-token-overrides($overrides: (), $token-maps) {
$valid-token-names: ();
Expand Down
82 changes: 56 additions & 26 deletions src/material/core/tokens/m3/_index.scss
Expand Up @@ -42,34 +42,35 @@
@use './mat/table' as tokens-mat-table;
@use './mat/toolbar' as tokens-mat-toolbar;
@use './mat/tree' as tokens-mat-tree;
// @use './mdc/checkbox' as tokens-mdc-checkbox;
// @use './mdc/text-button' as tokens-mdc-text-button;
// @use './mdc/protected-button' as tokens-mdc-protected-button;
// @use './mdc/filled-button' as tokens-mdc-filled-button;
// @use './mdc/outlined-button' as tokens-mdc-outlined-button;
// @use './mdc/chip' as tokens-mdc-chip;
// @use './mdc/circular-progress' as tokens-mdc-circular-progress;
// @use './mdc/dialog' as tokens-mdc-dialog;
// @use './mdc/elevated-card' as tokens-mdc-elevated-card;
// @use './mdc/extended-fab' as tokens-mdc-extended-fab;
// @use './mdc/fab' as tokens-mdc-fab;
// @use './mdc/fab-small' as tokens-mdc-fab-small;
// @use './mdc/form-field' as tokens-mdc-form-field;
// @use './mdc/filled-text-field' as tokens-mdc-filled-text-field;
// @use './mdc/icon-button' as tokens-mdc-icon-button;
// @use './mdc/linear-progress' as tokens-mdc-linear-progress;
// @use './mdc/list' as tokens-mdc-list;
// @use './mdc/outlined-card' as tokens-mdc-outlined-card;
// @use './mdc/outlined-text-field' as tokens-mdc-outlined-text-field;
// @use './mdc/plain-tooltip' as tokens-mdc-plain-tooltip;
// @use './mdc/radio' as tokens-mdc-radio;
// @use './mdc/slider' as tokens-mdc-slider;
// @use './mdc/snack-bar' as tokens-mdc-snack-bar;
// @use './mdc/switch' as tokens-mdc-switch;
// @use './mdc/tab' as tokens-mdc-tab;
// @use './mdc/tab-indicator' as tokens-mdc-tab-indicator;
@use './mdc/checkbox' as tokens-mdc-checkbox;
@use './mdc/text-button' as tokens-mdc-text-button;
@use './mdc/protected-button' as tokens-mdc-protected-button;
@use './mdc/filled-button' as tokens-mdc-filled-button;
@use './mdc/outlined-button' as tokens-mdc-outlined-button;
@use './mdc/chip' as tokens-mdc-chip;
@use './mdc/circular-progress' as tokens-mdc-circular-progress;
@use './mdc/dialog' as tokens-mdc-dialog;
@use './mdc/elevated-card' as tokens-mdc-elevated-card;
@use './mdc/extended-fab' as tokens-mdc-extended-fab;
@use './mdc/fab' as tokens-mdc-fab;
@use './mdc/fab-small' as tokens-mdc-fab-small;
@use './mdc/form-field' as tokens-mdc-form-field;
@use './mdc/filled-text-field' as tokens-mdc-filled-text-field;
@use './mdc/icon-button' as tokens-mdc-icon-button;
@use './mdc/linear-progress' as tokens-mdc-linear-progress;
@use './mdc/list' as tokens-mdc-list;
@use './mdc/outlined-card' as tokens-mdc-outlined-card;
@use './mdc/outlined-text-field' as tokens-mdc-outlined-text-field;
@use './mdc/plain-tooltip' as tokens-mdc-plain-tooltip;
@use './mdc/radio' as tokens-mdc-radio;
@use './mdc/slider' as tokens-mdc-slider;
@use './mdc/snack-bar' as tokens-mdc-snack-bar;
@use './mdc/switch' as tokens-mdc-switch;
@use './mdc/tab' as tokens-mdc-tab;
@use './mdc/tab-indicator' as tokens-mdc-tab-indicator;

$_module-names: (
// Custom tokens
tokens-mat-app,
tokens-mat-autocomplete,
tokens-mat-badge,
Expand Down Expand Up @@ -112,6 +113,35 @@ $_module-names: (
tokens-mat-text-button,
tokens-mat-toolbar,
tokens-mat-tree,

// MDC tokens
tokens-mdc-checkbox,
tokens-mdc-chip,
tokens-mdc-text-button,
tokens-mdc-protected-button,
tokens-mdc-filled-button,
tokens-mdc-outlined-button,
tokens-mdc-chip,
tokens-mdc-circular-progress,
tokens-mdc-dialog,
tokens-mdc-elevated-card,
tokens-mdc-extended-fab,
tokens-mdc-fab,
tokens-mdc-fab-small,
tokens-mdc-form-field,
tokens-mdc-filled-text-field,
tokens-mdc-icon-button,
tokens-mdc-linear-progress,
tokens-mdc-list,
tokens-mdc-outlined-card,
tokens-mdc-outlined-text-field,
tokens-mdc-plain-tooltip,
tokens-mdc-radio,
tokens-mdc-slider,
tokens-mdc-snack-bar,
tokens-mdc-switch,
tokens-mdc-tab,
tokens-mdc-tab-indicator,
);

/// Gets the full set of M3 tokens for the given theme object.
Expand Down
110 changes: 110 additions & 0 deletions src/material/core/tokens/m3/mdc/_checkbox.scss
@@ -0,0 +1,110 @@
@use 'sass:map';
@use 'sass:meta';
@use '../../token-utils';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mdc, checkbox);

/// Generates the tokens for MDC checkbox
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
/// @param {Map} $token-slots Possible token slots
/// @return {Map} A set of tokens for the MDC checkbox
@function get-tokens($systems, $exclude-hardcoded, $token-slots) {
$mdc-tokens: token-utils.get-mdc-tokens('checkbox', $systems, $exclude-hardcoded);
$variant-tokens: (
primary: (), // Default, no overrides needed
secondary: (
selected-container-color: map.get($systems, md-sys-color, secondary),
selected-focus-container-color: map.get($systems, md-sys-color, secondary),
selected-focus-icon-color: map.get($systems, md-sys-color, on-secondary),
selected-focus-state-layer-color: map.get($systems, md-sys-color, secondary),
selected-hover-container-color: map.get($systems, md-sys-color, secondary),
selected-hover-icon-color: map.get($systems, md-sys-color, on-secondary),
selected-hover-state-layer-color: map.get($systems, md-sys-color, secondary),
selected-icon-color: map.get($systems, md-sys-color, on-secondary),
selected-pressed-container-color: map.get($systems, md-sys-color, secondary),
selected-pressed-icon-color: map.get($systems, md-sys-color, on-secondary),
unselected-pressed-state-layer-color: map.get($systems, md-sys-color, secondary),
),
tertiary: (
selected-container-color: map.get($systems, md-sys-color, tertiary),
selected-focus-container-color: map.get($systems, md-sys-color, tertiary),
selected-focus-icon-color: map.get($systems, md-sys-color, on-tertiary),
selected-focus-state-layer-color: map.get($systems, md-sys-color, tertiary),
selected-hover-container-color: map.get($systems, md-sys-color, tertiary),
selected-hover-icon-color: map.get($systems, md-sys-color, on-tertiary),
selected-hover-state-layer-color: map.get($systems, md-sys-color, tertiary),
selected-icon-color: map.get($systems, md-sys-color, on-tertiary),
selected-pressed-container-color: map.get($systems, md-sys-color, tertiary),
selected-pressed-icon-color: map.get($systems, md-sys-color, on-tertiary),
unselected-pressed-state-layer-color: map.get($systems, md-sys-color, tertiary),
),
error: (
selected-container-color: map.get($systems, md-sys-color, error),
selected-focus-container-color: map.get($systems, md-sys-color, error),
selected-focus-icon-color: map.get($systems, md-sys-color, on-error),
selected-focus-state-layer-color: map.get($systems, md-sys-color, error),
selected-hover-container-color: map.get($systems, md-sys-color, error),
selected-hover-icon-color: map.get($systems, md-sys-color, on-error),
selected-hover-state-layer-color: map.get($systems, md-sys-color, error),
selected-icon-color: map.get($systems, md-sys-color, on-error),
selected-pressed-container-color: map.get($systems, md-sys-color, error),
selected-pressed-icon-color: map.get($systems, md-sys-color, on-error),
unselected-pressed-state-layer-color: map.get($systems, md-sys-color, error),
)
);

@return token-utils.namespace-tokens(
$prefix,
(
_fix-tokens($mdc-tokens),
token-utils.map-values($variant-tokens, meta.get-function(_fix-tokens))
),
$token-slots
);
}

/// Renames the official checkbox tokens to match the names actually used in MDC's code (which are
/// different). This is a temporary workaround until MDC updates to use the correct names for the
/// tokens.
/// @param {Map} $tokens The map of checkbox tokens with the official tokens names
/// @param {Map} $all-tokens Map of all checkbox tokens, including hardcoded values.
/// This is necessary in order to do opacity lookups.
/// @return {Map} The given tokens, renamed to be compatible with MDC's token implementation.
@function _fix-tokens($tokens) {
// Need to get the hardcoded values, because they include opacities that are used for the disabled
// state.
$hardcoded-tokens: token-utils.get-mdc-tokens('checkbox', (), false);

$rename-keys: (
selected-icon-color: selected-checkmark-color,
selected-disabled-icon-color: disabled-selected-checkmark-color,
selected-container-color: selected-icon-color,
selected-hover-container-color: selected-hover-icon-color,
selected-disabled-container-color: disabled-selected-icon-color,
selected-disabled-container-opacity: disabled-selected-icon-opacity,
selected-focus-container-color: selected-focus-icon-color,
selected-pressed-container-color: selected-pressed-icon-color,
unselected-disabled-outline-color: disabled-unselected-icon-color,
unselected-disabled-container-opacity: disabled-unselected-icon-opacity,
unselected-focus-outline-color: unselected-focus-icon-color,
unselected-hover-outline-color: unselected-hover-icon-color,
unselected-outline-color: unselected-icon-color,
unselected-pressed-outline-color: unselected-pressed-icon-color
);

$remapped-tokens: token-utils.rename-map-keys($tokens, $rename-keys);
$remapped-hardcoded-tokens: token-utils.rename-map-keys($hardcoded-tokens, $rename-keys);

@return token-utils.combine-color-tokens($remapped-tokens, $remapped-hardcoded-tokens, (
(
color: disabled-selected-icon-color,
opacity: disabled-selected-icon-opacity,
),
(
color: disabled-unselected-icon-color,
opacity: disabled-unselected-icon-opacity,
),
));
}
91 changes: 91 additions & 0 deletions src/material/core/tokens/m3/mdc/_chip.scss
@@ -0,0 +1,91 @@
@use 'sass:map';
@use '../../../style/sass-utils';
@use '../../token-utils';

// The prefix used to generate the fully qualified name for tokens in this file.
$prefix: (mdc, chip);

/// Generates the tokens for MDC chip
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $exclude-hardcoded Whether to exclude hardcoded token values
/// @param {Map} $token-slots Possible token slots
/// @return {Map} A set of tokens for the MDC chip
@function get-tokens($systems, $exclude-hardcoded, $token-slots) {
// MDC has a chip component, but they seem to have made up the tokens rather than using ones
// generated from the token database, therefore we need a custom token function for it.
$tokens: sass-utils.merge-all(
token-utils.generate-typography-tokens($systems, label-text, label-large),
(
container-shape: token-utils.hardcode((
family: rounded,
radius: 8px,
), $exclude-hardcoded),
with-avatar-avatar-size: token-utils.hardcode(24px, $exclude-hardcoded),
label-text-color: map.get($systems, md-sys-color, on-surface-variant),
disabled-label-text-color: sass-utils.safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.38,
),
with-icon-icon-size: token-utils.hardcode(18px, $exclude-hardcoded),
with-icon-icon-color: map.get($systems, md-sys-color, on-surface-variant),
with-icon-disabled-icon-color: map.get($systems, md-sys-color, on-surface),
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-secondary-container),
with-trailing-icon-trailing-icon-color: map.get($systems, md-sys-color, on-surface-variant),
with-trailing-icon-disabled-trailing-icon-color: map.get($systems, md-sys-color, on-surface),
focus-state-layer-opacity: map.get($systems, md-sys-state, focus-state-layer-opacity),
focus-state-layer-color: map.get($systems, md-sys-color, on-surface-variant),
outline-width: token-utils.hardcode(1px, $exclude-hardcoded),
outline-color: map.get($systems, md-sys-color, outline),
disabled-outline-color: sass-utils.safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.12,
),
focus-outline-color: map.get($systems, md-sys-color, on-surface-variant),
hover-state-layer-color: map.get($systems, md-sys-color, on-surface-variant),
hover-state-layer-opacity: map.get($systems, md-sys-state, hover-state-layer-opacity),
with-avatar-disabled-avatar-opacity: token-utils.hardcode(0.38, $exclude-hardcoded),
elevated-selected-container-color: map.get($systems, md-sys-color, secondary-container),
flat-selected-outline-width: token-utils.hardcode(0, $exclude-hardcoded),
selected-label-text-color: map.get($systems, md-sys-color, on-secondary-container),
flat-disabled-selected-container-color: sass-utils.safe-color-change(
map.get($systems, md-sys-color, on-surface),
$alpha: 0.12,
),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-secondary-container),
selected-hover-state-layer-opacity:
map.get($systems, md-sys-state, hover-state-layer-opacity),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-secondary-container),
selected-focus-state-layer-opacity:
map.get($systems, md-sys-state, focus-state-layer-opacity),
with-icon-disabled-icon-opacity: token-utils.hardcode(0.38, $exclude-hardcoded),
with-trailing-icon-disabled-trailing-icon-opacity:
token-utils.hardcode(0.38, $exclude-hardcoded),
),
), (
// Color variants:
primary: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-primary-container),
elevated-selected-container-color: map.get($systems, md-sys-color, primary-container),
selected-label-text-color: map.get($systems, md-sys-color, on-primary-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-primary-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-primary-container),
),
secondary: (), // Default, no overrides needed.
tertiary: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-tertiary-container),
elevated-selected-container-color: map.get($systems, md-sys-color, tertiary-container),
selected-label-text-color: map.get($systems, md-sys-color, on-tertiary-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-tertiary-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-tertiary-container),
),
error: (
with-icon-selected-icon-color: map.get($systems, md-sys-color, on-error-container),
elevated-selected-container-color: map.get($systems, md-sys-color, error-container),
selected-label-text-color: map.get($systems, md-sys-color, on-error-container),
selected-hover-state-layer-color: map.get($systems, md-sys-color, on-error-container),
selected-focus-state-layer-color: map.get($systems, md-sys-color, on-error-container),
)
);

@return token-utils.namespace-tokens($prefix, $tokens, $token-slots);
}

0 comments on commit f245153

Please sign in to comment.