Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(multiple): fallback to system level variables #29480

Merged
merged 7 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/material/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
@forward './core/typography/typography' show typography-hierarchy;
@forward './core/typography/typography-utils' show font-shorthand;
@forward './core/tokens/m2' show m2-tokens-from-theme;
@forward './core/tokens/m3-tokens' show system-level-colors, system-level-typography;
@forward './core/tokens/m3-tokens' show system-level-colors,
system-level-typography, system-level-elevation, system-level-shape,
system-level-motion, system-level-state;

// Private/Internal
@forward './core/density/private/all-density' show all-component-densities;
Expand Down
5 changes: 5 additions & 0 deletions src/material/core/style/_elevation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@use 'sass:meta';
@use 'sass:string';
@use './variables';
@use './sass-utils';

$_umbra-opacity: 0.2;
$_penumbra-opacity: 0.14;
Expand Down Expand Up @@ -143,6 +144,10 @@ $prefix: 'mat-elevation-z';
@return null;
}

@if (sass-utils.is-css-var-name($zValue)) {
@return $zValue;
}

@if meta.type-of($zValue) != number or not math.is-unitless($zValue) {
@error '$zValue must be a unitless number, but received `#{$zValue}`';
}
Expand Down
22 changes: 20 additions & 2 deletions src/material/core/style/_sass-utils.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@use 'sass:color';
@use 'sass:string';
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
Expand Down Expand Up @@ -64,12 +65,23 @@ $use-system-typography-variables: false;
/// A version of the Sass `color.change` function that is safe ot use with CSS variables.
@function safe-color-change($color, $args...) {
$args: meta.keywords($args);
$use-color-mix: $use-system-color-variables or
(is-css-var-name($color) and string.index($color, '--mat') == 1);
@if (meta.type-of($color) == 'color') {
@return color.change($color, $args...);
}
@else if ($color != null and map.get($args, alpha) != null and $use-system-color-variables) {
@else if ($color != null and
map.get($args, alpha) != null and $use-color-mix) {
$opacity: map.get($args, alpha);
@return #{color-mix(in srgb, #{$color} #{($opacity * 100) + '%'}, transparent)};
@if meta.type-of($opacity) == number {
$opacity: ($opacity * 100) + '%';
}

@if (is-css-var-name($color)) {
$color: var($color);
}

@return #{color-mix(in srgb, #{$color} #{$opacity}, transparent)};
}
@return $color;
}
Expand All @@ -91,3 +103,9 @@ $use-system-typography-variables: false;
}
@return $kwargs;
}

// Returns whether the $value is a CSS variable name based on whether it's a string prefixed
// by "--".
@function is-css-var-name($value) {
@return meta.type-of($value) == string and string.index($value, '--') == 1;
}
118 changes: 106 additions & 12 deletions src/material/core/tokens/_m3-tokens.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
@use './m3';
@use './m3/definitions' as m3-token-definitions;
@use '../tokens/m2' as m2-tokens;
@use '../style/elevation';
@use './density';
@use './format-tokens';

// Default system level prefix to use when directly calling the `system-level-*` mixins
$_system-level-prefix: sys;

// Prefix used for component token fallback variables, e.g.
// `color: var(--mdc-text-button-label-text-color, var(--mat-app-primary));`
$_system-fallback-prefix: mat-app;

/// Generates tokens for the given palette with the given prefix.
/// @param {Map} $palette The palette to generate tokens for
/// @param {String} $prefix The key prefix used to name the tokens
Expand Down Expand Up @@ -86,8 +94,9 @@ $_cached-token-slots: null;
/// Generates a set of namespaced tokens for all components.
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $include-non-systemized Whether to include non-systemized tokens
andrewseguin marked this conversation as resolved.
Show resolved Hide resolved
/// @param {Boolean} $include-density Whether to include density tokens
/// @return {Map} A map of namespaced tokens
@function _generate-tokens($systems, $include-non-systemized: false) {
@function _generate-tokens($systems, $include-non-systemized: false, $include-density: false) {
$systems: map.merge((
md-sys-color: (),
md-sys-elevation: (),
Expand Down Expand Up @@ -116,16 +125,63 @@ $_cached-token-slots: null;
// Strip out tokens that are systemized by our made up density system.
@each $namespace, $tokens in $result {
@each $token, $value in $tokens {
@if density.is-systemized($namespace, $token) {
@if density.is-systemized($namespace, $token) and not $include-density {
$tokens: map.remove($tokens, $token);
}
}
$result: map.set($result, $namespace, $tokens);
}

@return $result;
}

@mixin system-level-colors($theme, $overrides: ()) {
// Return a new map where the values are the same as the provided map's
// keys, prefixed with "--mat-app-". For example:
// (key1: '', key2: '') --> (key1: --mat-app-key1, key2: --mat-app-key2)
@function _create-system-app-vars-map($map) {
$new-map: ();
@each $key, $value in $map {
$new-map: map.set($new-map, $key, --#{$_system-fallback-prefix}-#{$key});
}
@return $new-map;
}

// Create a components tokens map where values are based on
// system fallback variables referencing Material's system keys.
// Includes density token fallbacks where density is 0.
@function create-system-fallbacks() {
$app-vars: (
'md-sys-color':
_create-system-app-vars-map(m3-token-definitions.md-sys-color-values-light()),
'md-sys-typescale':
_create-system-app-vars-map(m3-token-definitions.md-sys-typescale-values()),
'md-sys-elevation':
_create-system-app-vars-map(m3-token-definitions.md-sys-elevation-values()),
'md-sys-state':
_create-system-app-vars-map(m3-token-definitions.md-sys-state-values()),
'md-sys-shape':
_create-system-app-vars-map(m3-token-definitions.md-sys-shape-values()),
);

@return sass-utils.deep-merge-all(
_generate-tokens($app-vars, true, true),
generate-density-tokens(0)
);
}

// Emits CSS variables for Material's system level values. Uses the
// namespace prefix in $_system-fallback-prefix.
// e.g. --mat-app-surface: #E5E5E5
@mixin theme($theme, $overrides: ()) {
@include system-level-colors($theme, $overrides, $_system-fallback-prefix);
@include system-level-typography($theme, $overrides, $_system-fallback-prefix);
@include system-level-elevation($theme, $overrides, $_system-fallback-prefix);
@include system-level-shape($theme, $overrides, $_system-fallback-prefix);
@include system-level-motion($theme, $overrides, $_system-fallback-prefix);
@include system-level-state($theme, $overrides, $_system-fallback-prefix);
}

@mixin system-level-colors($theme, $overrides: (), $prefix: null) {
$palettes: map.get($theme, _mat-theming-internals-do-not-access, palettes);
$base-palettes: (
neutral: map.get($palettes, neutral),
Expand All @@ -135,12 +191,15 @@ $_cached-token-slots: null;
);

$type: map.get($theme, _mat-theming-internals-do-not-access, theme-type);
$system-variables-prefix: map.get($theme, _mat-theming-internals-do-not-access,
color-system-variables-prefix) or sys;
$primary: map.merge(map.get($palettes, primary), $base-palettes);
$tertiary: map.merge(map.get($palettes, tertiary), $base-palettes);
$error: map.get($palettes, error);

@if (not $prefix) {
$prefix: map.get($theme, _mat-theming-internals-do-not-access,
color-system-variables-prefix) or $_system-level-prefix;
}

$ref: (
md-ref-palette: _generate-ref-palette-tokens($primary, $tertiary, $error)
);
Expand All @@ -150,27 +209,28 @@ $_cached-token-slots: null;
m3-token-definitions.md-sys-color-values-light($ref));

@each $name, $value in $sys-colors {
--#{$system-variables-prefix}-#{$name}: #{map.get($overrides, $name) or $value};
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}

@mixin system-level-typography($theme, $overrides: ()) {
@mixin system-level-typography($theme, $overrides: (), $prefix: null) {
$font-definition: map.get($theme, _mat-theming-internals-do-not-access, font-definition);
$brand: map.get($font-definition, brand);
$plain: map.get($font-definition, plain);
$bold: map.get($font-definition, bold);
$medium: map.get($font-definition, medium);
$regular: map.get($font-definition, regular);
$system-variables-prefix: map.get($theme, _mat-theming-internals-do-not-access,
typography-system-variables-prefix) or sys;
$ref: (
md-ref-typeface: _generate-ref-typeface-tokens($brand, $plain, $bold, $medium, $regular)
);

$sys-typescale: m3-token-definitions.md-sys-typescale-values($ref);
@if (not $prefix) {
$prefix: map.get($theme, _mat-theming-internals-do-not-access,
typography-system-variables-prefix) or $_system-level-prefix;
}

@each $name, $value in $sys-typescale {
--#{$system-variables-prefix}-#{$name}: #{map.get($overrides, $name) or $value};
@each $name, $value in m3-token-definitions.md-sys-typescale-values($ref) {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}

Expand All @@ -182,6 +242,40 @@ $_cached-token-slots: null;
@return $result;
}

@mixin system-level-elevation($theme, $overrides: (), $prefix: $_system-level-prefix) {
$shadow-color: map.get(
$theme, _mat-theming-internals-do-not-access, color-tokens, (mdc, theme), shadow);

@for $level from 0 through 24 {
$value: elevation.get-box-shadow($level, $shadow-color);
--#{$prefix}-elevation-shadow-level-#{$level}: #{$value};
}

@each $name, $value in m3-token-definitions.md-sys-elevation-values() {
$level: map.get($overrides, $name) or $value;
$value: elevation.get-box-shadow($level, $shadow-color);
--#{$prefix}-#{$name}: #{$value};
}
}

@mixin system-level-shape($theme, $overrides: (), $prefix: $_system-level-prefix) {
@each $name, $value in m3-token-definitions.md-sys-shape-values() {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}

@mixin system-level-state($theme, $overrides: (), $prefix: $_system-level-prefix) {
@each $name, $value in m3-token-definitions.md-sys-state-values() {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}

@mixin system-level-motion($theme, $overrides: (), $prefix: $_system-level-prefix) {
@each $name, $value in m3-token-definitions.md-sys-motion-values() {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}

@function _get-sys-color($type, $ref, $prefix) {
$mdc-sys-color: if($type == dark,
m3-token-definitions.md-sys-color-values-dark($ref),
Expand Down
6 changes: 6 additions & 0 deletions src/material/core/tokens/_token-definition.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@use '../m2/palette' as m2-palette;
@use '../m2/theming' as m2-theming;
@use '../m2/typography' as m2-typography;
@use '../style/sass-utils';
@use './m3/definitions' as m3-token-definitions;

// Indicates whether we're building internally. Used for backwards compatibility.
Expand Down Expand Up @@ -161,6 +162,11 @@ $_system-fallbacks: null;
$color-key: map.get($pair, color);
$opacity-key: map.get($pair, opacity);
$color: map.get($tokens, $color-key);

@if (sass-utils.is-css-var-name($color)) {
$color: var(#{$color});
}

$opacity: map.get($opacity-lookup, $opacity-key);

@if(meta.type-of($color) == 'color') {
Expand Down
Loading
Loading