Extending Angular Material Theme System: Additional Shades
Tags: angular, angularmaterial, theming, scss
Published: 2021-04-16 11:39:35

In [Part 1](https://dev.to/martinmcwhorter/extending-angular-material-theme-system-n50) of this series, we discussed how the Angular Material theme system is a powerful tool that may seem overly opinionated. In reality it is very extendable. 

 * In the previous example we added a palette to the theme. 
 * In this example we will add additional named hues to palettes. 

Angular Material gives you a `lighter` and `darker` named color in each palette -- but these may not be enough for your organization or project. 

```scss
  mat-color($primary, lighter);
  mat-color($primary, darker); 
```

We are going to add additional helpers `extra-light` and `extra-dark`. First we are going to go over a few fundamentals. 
  
## Quick Detour

Quick definitions of hue, tint, shade and tone. 

Hue = a pure color. 
Tint = hue + white
Shade = hue + black
Tone = hue + grey 

A hue is a mix of primary colors (red, blue and green are the primary colors of light, where red, yellow and blue are the primary colors of pigment). Tints, shades and tones vary to give gradients.

## Theme Palettes  

Let's look at a theme pallets and see how they work. 

Each palette starts as a map (like a dictionary or array) of shades and tints, with a key starting from `50` to `900` going from brightest to darkest -- then `A100` to `A700` with a gamma shift into pastel tints.

Then a key of `contrast` containing another map containing a text contrast shade or tint for each of the keys. 

```scss
$mat-red: (
  50: #ffebee,
  100: #ffcdd2,
  200: #ef9a9a,
  300: #e57373,
  400: #ef5350,
  500: #f44336,
  600: #e53935,
  700: #d32f2f,
  800: #c62828,
  900: #b71c1c,
  A100: #ff8a80,
  A200: #ff5252,
  A400: #ff1744,
  A700: #d50000,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
    A100: $dark-primary-text,
    A200: $light-primary-text,
    A400: $light-primary-text,
    A700: $light-primary-text,
  )
);
```

A palette is then created by passing this map to the `mat-palette(..)` (being renamed to `define-palette(..)`) function. 

```scss
$primary: mat-palette($base-palette: $mat-red, $lighter: 100, $darker: 700); 
```

## Adding additional helpers

We are now going to extend the `mat-pallete()` (or `define-palette()`) function. 

```scss
@function my-palette($base-palette, $default: 500, $lighter: 100, $darker: 700, $extra-light: 50, $extra-dark: 900, $text: $default) {
  $new-palette: mat-palette($base-palette, $default, $lighter, $darker, $text: $default);

  $extra-palette: (
    extra-light: map-get($base-palette, $extra-light),
    extra-dark: map-get($base-palette, $extra-dark),
    extra-light-contrast: mat-contrast($base-palette, $extra-light),
    extra-dark-contrast: mat-contrast($base-palette, $extra-dark),
  );

  @return map_merge($new-palette, $extra-palette);
}
```

Now we can update our example above and get a palette with the `extra-light` and `extra-dark` helpers. 

```scss
$primary: my-palette(
  $base-palette: $mat-red, 
  $lighter: 100, 
  $darker: 700, 
  $extra-light: 50, 
  $extra-dark: 900); 

$light-theme: mat-light-theme($primary, ...);

// elsewhere in a component theme 
@mixin some-theme($theme) {
  $primary: map-get($theme, primary);

  $primary-lighter: mat-color($primary, lighter);
  $primary-darker: mat-color($primary, darker);
  $primary-extra-light: mat-color($primary, extra-light);
  $primary-extra-dark: mat-color($primary, extra-dark); 
}
```

## Conclusion 

There we have it. Designers and developers can use `extra-light` and `extra-dark` as named shades or tints in designs and implementations.

Your use case will likely be different. You can suit these techniques to your own situation.