Understanding the Angular Material define-palette SASS Function | Task

Ole Ersoy
May - 26  -  5 min

Scenario

We would like a breakdown of the result of applying the define-palette function (Formerly mat-palette ) as follows.

$theme-accent: mat.define-palette(mat.$cyan-palette);

Approach

If we @debug mat.#cyan-palette we see that it contains the following SASS map with hue key to color values. The hue keys range from 50 to 900, with the addition of the accent colors A100, A200, A400, and A700.

In addition it contains a nested contrast map that has the same range of hue keys

( 50: #e0f7fa, 
 100: #b2ebf2, 
 200: #80deea, 
 300: #4dd0e1, 
 400: #26c6da, 
 500: #00bcd4, 
 600: #00acc1, 
 700: #0097a7, 
 800: #00838f, 
 900: #006064, 
 A100: #84ffff, 
 A200: #18ffff, 
 A400: #00e5ff, 
 A700: #00b8d4, 
 contrast: (
    50: rgba(0, 0, 0, 0.87), 
    100: rgba(0, 0, 0, 0.87), 
    200: rgba(0, 0, 0, 0.87), 
    300: rgba(0, 0, 0, 0.87), 
    400: rgba(0, 0, 0, 0.87), 
    500: white, 
    600: white, 
    700: white, 
    800: white, 
    900: white, 
    A100: rgba(0, 0, 0, 0.87), 
    A200: rgba(0, 0, 0, 0.87), 
    A400: rgba(0, 0, 0, 0.87), 
    A700: rgba(0, 0, 0, 0.87)))

If we @debug $theme-accent we see that it contains.

( 50: #e0f7fa, 
 100: #b2ebf2, 
 200: #80deea, 
 300: #4dd0e1, 
 400: #26c6da, 
 500: #00bcd4, 
 600: #00acc1, 
 700: #0097a7, 
 800: #00838f, 
 900: #006064, 
 A100: #84ffff, 
 A200: #18ffff, 
 A400: #00e5ff, 
 A700: #00b8d4, 
 contrast: (
    50: rgba(0, 0, 0, 0.87), 
    100: rgba(0, 0, 0, 0.87), 
    200: rgba(0, 0, 0, 0.87), 
    300: rgba(0, 0, 0, 0.87), 
    400: rgba(0, 0, 0, 0.87), 
    500: white, 
    600: white, 
    700: white, 
    800: white, 
    900: white, 
    A100: rgba(0, 0, 0, 0.87), 
    A200: rgba(0, 0, 0, 0.87), 
    A400: rgba(0, 0, 0, 0.87), 
    A700: rgba(0, 0, 0, 0.87)))
default: #00bcd4, 
lighter: #b2ebf2, 
darker: #0097a7, 
text: #00bcd4, 
default-contrast: white, 
lighter-contrast: rgba(0, 0, 0, 0.87), 
darker-contrast: white, 
"50-contrast": rgba(0, 0, 0, 0.87), 
"100-contrast": rgba(0, 0, 0, 0.87), 
"200-contrast": rgba(0, 0, 0, 0.87), 
"300-contrast": rgba(0, 0, 0, 0.87), 
"400-contrast": rgba(0, 0, 0, 0.87), 
"500-contrast": white, 
"600-contrast": white, 
"700-contrast": white, 
"800-contrast": white, 
"900-contrast": white, 
"A100-contrast": rgba(0, 0, 0, 0.87), 
"A200-contrast": rgba(0, 0, 0, 0.87), 
"A400-contrast": rgba(0, 0, 0, 0.87), 
"A700-contrast": rgba(0, 0, 0, 0.87), 
"contrast-contrast": null)

To understand how this result was generated lets have a look at the source code for define-palette.

/// Creates a map of hues to colors for a theme. This is used to define a theme palette in terms
/// of the Material Design hues.
/// @param {Map} $base-palette Map of hue keys to color values for the basis for this palette.
/// @param {String | Number} $default Default hue for this palette.
/// @param {String | Number} $lighter "lighter" hue for this palette.
/// @param {String | Number} $darker "darker" hue for this palette.
/// @param {String | Number} $text "text" hue for this palette.
/// @returns {Map} A complete Angular Material theming palette.
@function define-palette($base-palette, $default: 500, $lighter: 100, $darker: 700,
  $text: $default) {
  $result: map.merge($base-palette, (
    default: _get-color-from-palette($base-palette, $default),
    lighter: _get-color-from-palette($base-palette, $lighter),
    darker: _get-color-from-palette($base-palette, $darker),
    text: _get-color-from-palette($base-palette, $text),

    default-contrast: get-contrast-color-from-palette($base-palette, $default),
    lighter-contrast: get-contrast-color-from-palette($base-palette, $lighter),
    darker-contrast: get-contrast-color-from-palette($base-palette, $darker)
  ));

  // For each hue in the palette, add a "-contrast" color to the map.
  @each $hue, $color in $base-palette {
    $result: map.merge($result, (
      '#{$hue}-contrast': get-contrast-color-from-palette($base-palette, $hue)
    ));
  }

  @return $result;

So the define-palette function takes the a material color palette along with the default, lighter, darker, and text hue key values and uses these to augment the passed in color palette with additional values.

The block.

$result: map.merge($base-palette, (    default: _get-color-from-palette($base-palette, $default),    lighter: _get-color-from-palette($base-palette, $lighter),    darker: _get-color-from-palette($base-palette, $darker),    text: _get-color-from-palette($base-palette, $text),     default-contrast: get-contrast-color-from-palette($base-palette, $default),    lighter-contrast: get-contrast-color-from-palette($base-palette, $lighter),    darker-contrast: get-contrast-color-from-palette($base-palette, $darker)  ));

Merges in color values for the default, lighter, darker, and text keys, as well as the corresponding contrast values for these.

The block.

// For each hue in the palette, add a "-contrast" color to the map.  @each $hue, $color in $base-palette {    $result: map.merge($result, (      '#{$hue}-contrast': get-contrast-color-from-palette($base-palette, $hue)    ));  }

Gives us access to the contrast values contained in the nested contrast map within the main map. Each constrast key is postfixed with -contrast.

This new augmented palette can be used with Angular Materials get-color-from-palette function to retrieve color values. Here is an example from the Angular Material documentation.

@use '@angular/material' as mat;

$my-palette: mat.define-palette(mat.$indigo-palette);

.my-custom-style {
 background: mat.get-color-from-palette($my-palette, '500');
 color: mat.get-color-from-palette($my-palette, '500-contrast');
}

Demo