Theming Pattern for Extending Angular Material Components

Ole Ersoy
3 min readMay 18, 2023
Image by Bich Nguyen Vo from Pixabay

Scenario

We want to create a SASS mixin for the for extending the colors of the Fab Button with success , danger , and info colors following a simple repeatable pattern.

Approach

We will extend the theming of Angular Material per component allowing us to import theme extensions in a minimal fashion when creating light weight applications.

In order to do this we will implement a theming template like this one for the Fab Button component.

@use "sass:map";
@use "@angular/material" as mat;

@mixin structure($theme) {}

@mixin color($theme) {}

@mixin typography($theme) {}

@mixin density($theme) {}

@mixin theme($theme) {
$color: mat.get-color-config($theme);
$density: mat.get-density-config($theme);
$typography: mat.get-typography-config($theme);

@if $color != null {
//==========================================
// Note that we pass in $theme
// to avoid any restructing that
// mat.get-color-config might do.
//==========================================
@include color($theme);
}
@if $density != null {
@include density($density);
}
@if $typography != null {
@include typography($typography);
}
@include structure($theme);
}

Note themes that call the theme mixin for a specific component will get the components structure style included automatically (No if check) .

This is fine since calling the theme function should be done for the default style only, and all other themes that are non default, should change colors only, since styles like structure and typography should be defined in the default theme.

Here’s the implementation. We delegate styling for each color variation to fab-variant .

@use "sass:map";
@use "@angular/material" as mat;
@use "@material/theme/theme-color" as mdc-theme-color;
@use "./fab-variant" as *;
@use "../common/colors" as *;

@mixin color($theme) {
$colors: colors($theme);
//==========================================
// Use the same approach that
// _fab-theme.scss uses.
//==========================================
.mat-mdc-fab {
@include fab-variant(
mat-success,
map.get($colors, on-success),
map.get($colors, success)
);
@include fab-variant(
mat-danger,
map.get($colors, on-danger),
map.get($colors, danger)
);
@include fab-variant(
mat-info,
map.get($colors, on-info),
map.get($colors, info)
);
}
}

@mixin structure($theme) {}

@mixin typography($theme) {}

@mixin density($theme) {}

@mixin theme($theme) {
$color: mat.get-color-config($theme);
$density: mat.get-density-config($theme);
$typography: mat.get-typography-config($theme);

@if $color != null {
//==========================================
// Note that we pass in $theme
// to avoid any restructing that
// mat.get-color-config might do.
//==========================================
@include color($theme);
}
@if $density != null {
@include density($density);
}
@if $typography != null {
@include typography($typography);
}
}

Applications that want to extend the theming colors for the Fab button only need to import this SASS module.

The fab-variant mixin delegates to the Material Component Web @material/fab/fab-theme mixin to generate the CSS variables for the color context and calls the locally defined ripple-color , which creates the variables for the ripple color.

@use '@material/fab/fab-theme' as mdc-fab-theme;
@use '../common/' as *;

@mixin fab-variant($color-class, $foreground, $background) {
&.#{ $color-class } {
@include mdc-fab-theme.theme(
(
container-color: $background,
icon-color: $foreground,
)
);
background-color: var(--mdc-fab-container-color, transparent);
color: var(--mdc-fab-icon-color, inherit);
@include ripple-color($foreground);
}
}

The ripple color mixin is defined like this.

/**
* Define the ripple color variables.
*/
@mixin ripple-color($color) {
--mat-mdc-button-persistent-ripple-color: #{$color};
--mat-mdc-button-ripple-color: #{rgba($color, 0.1)};
}

Demo

The fab-variant code is contained in the foldersrc/fab-variant .

There’s also a el-theme.scss used to extend the Angular Material defined theme with success , danger , and info colors.

--

--