sass-references/angular-material/material/core/tokens/_m3-system.scss

273 lines
10 KiB
SCSS
Raw Permalink Normal View History

2024-12-06 10:42:08 +08:00
@use '../style/elevation';
@use '../style/sass-utils';
@use '../theming/config-validation';
@use '../theming/definition';
@use './m3/definitions';
@use 'sass:map';
@use 'sass:meta';
@use 'sass:list';
@use './m3-tokens';
/// Emits necessary CSS variables for Material's system level values for the values defined in the
/// config map. The config map can have values color, typography, and/or density.
///
/// If the config map's color value is an Angular Material color palette, it will be used as the
/// primary and tertiary colors with a `color-scheme` theme type. Otherwise if the color value is a
/// map, it must have a `primary` value containing an Angular Material color palette, and
/// optionally a different `tertiary` palette (defaults to primary palette) and `theme-type` that
/// is either `light`, `dark`, or 'color-scheme` (defaults to `color-scheme`). Color variable
/// definitions will not be emitted if there are no color values in the config.
///
/// If the config map's typography value is a font family string, it will be used as the
/// plain and brand font family with default bold, medium, and regular weights of 700, 500, and 400,
/// respectfully. Otherwise if the typography value is a map, it must have a `plain-family` font
/// family value, and optionally a different `brand-family` font family (defaults to the plain
/// value) and weights for `bold-weight` (default: 700), `bold-weight` (default: 500), and
/// `bold-weight` (default: 400). Typography variable definitions will not be emitted if there are
/// no typography values in the config.
///
/// If the config map's density value is a number, it will be used as the density scale. Otherwise
/// if the density value is a map, it must have a `scale` value. Density variable definitions will
/// not be emitted if there are no density values in the config.
///
/// The application variables emitted use the namespace prefix "--mat-sys".
/// e.g. --mat-sys-surface: #E5E5E5
///
/// @param {Map} $config The color configuration with optional keys color, typography, or density.
@mixin theme($config, $overrides: ()) {
$color: map.get($config, color);
$color-config: null;
@if ($color) {
// validate-palette returns null if it is a valid M3 palette
$is-palette: config-validation.validate-palette($color) == null;
// Default to "color-scheme" theme type if the config's color does not provide one.
@if (not $is-palette and not map.has-key($color, theme-type)) {
$color: map.set($color, theme-type, color-scheme);
}
$color-config: if($is-palette,
definition.define-colors((primary: $color, theme-type: color-scheme)),
definition.define-colors($color));
@include system-level-colors($color-config, $overrides, definition.$system-fallback-prefix);
@include system-level-elevation($color-config, $overrides, definition.$system-fallback-prefix);
}
$typography: map.get($config, typography);
$typography-config: null;
@if ($typography) {
$typography-config: if(meta.type-of($typography) == 'map',
definition.define-typography($typography),
definition.define-typography((plain-family: $typography)));
@include system-level-typography(
$typography-config, $overrides, definition.$system-fallback-prefix);
}
$density: map.get($config, density);
$density-config: null;
@if ($density) {
$density-config: if(meta.type-of($density) == 'map',
definition.define-density($density),
definition.define-density((scale: $density)));
$scale: map.get($density-config, _mat-theming-internals-do-not-access, density-scale);
@if ($scale != 0) {
$all-tokens: m3-tokens.generate-density-tokens($scale);
@each $component-tokens in $all-tokens {
$namespace: list.nth($component-tokens, 1);
@each $tokens in list.nth($component-tokens, 2) {
--#{list.nth($namespace, 1)}-#{list.nth($namespace, 2)}-#{
list.nth($tokens, 1)}: #{list.nth($tokens, 2)};
}
}
}
}
@include system-level-shape($overrides: $overrides, $prefix: definition.$system-fallback-prefix);
@include system-level-state($overrides: $overrides, $prefix: definition.$system-fallback-prefix);
}
/// Emits the system-level CSS variables for each of the provided override values. E.g. to
/// change the primary color to red, use `mat.theme-overrides((primary: red));`
@mixin theme-overrides($overrides, $prefix: definition.$system-fallback-prefix) {
$sys-names: map-merge-all(
definitions.md-sys-color-values-light(),
definitions.md-sys-typescale-values(),
definitions.md-sys-elevation-values(),
definitions.md-sys-shape-values(),
definitions.md-sys-state-values());
& {
@each $name, $value in $overrides {
@if (map.has-key($sys-names, $name)) {
--#{$prefix}-#{$name}: #{map.get($overrides, $name)};
}
}
}
}
@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),
neutral-variant: map.get($palettes, neutral-variant),
secondary: map.get($palettes, secondary),
error: map.get($palettes, error),
);
$type: map.get($theme, _mat-theming-internals-do-not-access, theme-type);
$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 definition.$system-level-prefix;
}
$ref: (
md-ref-palette: m3-tokens.generate-ref-palette-tokens($primary, $tertiary, $error)
);
$sys-colors: _generate-sys-colors($ref, $type);
// Manually insert a subset of palette values that are used directly by components
// instead of system variables.
$sys-colors: map.set($sys-colors,
'neutral-variant20', map.get($ref, md-ref-palette, neutral-variant20));
$sys-colors: map.set($sys-colors,
'neutral10', map.get($ref, md-ref-palette, neutral10));
& {
@each $name, $value in $sys-colors {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}
}
@function _generate-sys-colors($ref, $type) {
$light-sys-colors: definitions.md-sys-color-values-light($ref);
@if ($type == light) {
@return $light-sys-colors;
}
$dark-sys-colors: definitions.md-sys-color-values-dark($ref);
@if ($type == dark) {
@return $dark-sys-colors;
}
@if ($type == color-scheme) {
$light-dark-sys-colors: ();
@each $name, $light-value in $light-sys-colors {
$dark-value: map.get($dark-sys-colors, $name);
$light-dark-sys-colors:
map.set($light-dark-sys-colors, $name, light-dark($light-value, $dark-value));
}
@return $light-dark-sys-colors;
}
@error 'Unknown theme-type provided: #{$type}';
}
@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);
$ref: (md-ref-typeface:
m3-tokens.generate-ref-typeface-tokens($brand, $plain, $bold, $medium, $regular)
);
@if (not $prefix) {
$prefix: map.get($theme, _mat-theming-internals-do-not-access,
typography-system-variables-prefix) or definition.$system-level-prefix;
}
& {
@each $name, $value in definitions.md-sys-typescale-values($ref) {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}
}
@mixin system-level-elevation($theme, $overrides: (), $prefix: definition.$system-level-prefix) {
$shadow-color: map.get(
$theme, _mat-theming-internals-do-not-access, color-tokens, (mdc, theme), shadow);
@each $name, $value in 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: definition.$system-level-prefix) {
& {
@each $name, $value in definitions.md-sys-shape-values() {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}
}
@mixin system-level-state($theme: (), $overrides: (), $prefix: definition.$system-level-prefix) {
& {
@each $name, $value in definitions.md-sys-state-values() {
--#{$prefix}-#{$name}: #{map.get($overrides, $name) or $value};
}
}
}
// Return a new map where the values are the same as the provided map's
// keys, prefixed with "--mat-sys-". For example:
// (key1: '', key2: '') --> (key1: --mat-sys-key1, key2: --mat-sys-key2)
@function _create-system-app-vars-map($map) {
$new-map: ();
@each $key, $value in $map {
$new-map: map.set($new-map, $key, --#{definition.$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(definitions.md-sys-color-values-light()),
'md-sys-typescale':
_create-system-app-vars-map(definitions.md-sys-typescale-values()),
'md-sys-elevation':
_create-system-app-vars-map(definitions.md-sys-elevation-values()),
'md-sys-state':
_create-system-app-vars-map(definitions.md-sys-state-values()),
'md-sys-shape':
_create-system-app-vars-map(definitions.md-sys-shape-values()),
// Add a subset of palette-specific colors used by components instead of system values
'md-ref-palette':
_create-system-app-vars-map(
(
neutral10: '', // Form field native select option text color
neutral-variant20: '', // Sidenav scrim (container background shadow when opened),
)
),
);
@return sass-utils.deep-merge-all(
m3-tokens.generate-tokens($app-vars, true, true),
m3-tokens.generate-density-tokens(0)
);
}
/// Creates a single merged map from the provided variable-length map arguments
@function map-merge-all($maps...) {
$result: ();
@each $map in $maps {
$result: map.merge($result, $map);
}
@return $result;
}