Updating Angular Material 18 to 19

We will learn how to update Angular Material 18 to 19.

Demo in Angular Material 18

I am going to use the same demo as in the previous course, you can clone it from here.

Updating Angular Material 18 to 19

1. Checking for updates

Terminal window
ng update

2. Update Angular CLI

Terminal window
ng update @angular/cli

3. Update Angular Material

Terminal window
ng update @angular/material

Style changes for Angular Material 19

1. Updates in main theme file

We will start with making changes in main theme file at src/styles.scss.

1.1 Remove redundant mixin usages

As we already have them outside, remove usage of mat.elevation-classes and mat.app-background mixins from withing :root selector.

@include mat.elevation-classes();
@include mat.app-background();
:root {
@include mat.elevation-classes(themes.$my-app-theme);
@include mat.app-background(themes.$my-app-theme);
}

1.2 Remove individual component themes

:root {
@include mat.button-theme(themes.$my-app-theme);
@include mat.icon-theme(themes.$my-app-theme);
@include mat.menu-theme(themes.$my-app-theme);
@include mat.form-field-theme(themes.$my-app-theme);
@include mat.input-theme(themes.$my-app-theme);
}

1.3 Changes for typography

Move typography mixin outside of :root and remove usage of themes.$my-app-theme in it.

@include mat.typography-hierarchy(
mat.define-theme(
(
typography: (
use-system-variables: true,
system-variables-prefix: mat-sys,
),
)
)
);
:root {
@include mat.typography-hierarchy(themes.$my-app-theme);
}

1.4 Use new theme mixin

:root {
@include mat.theme(
(
color: (
primary: mat.$azure-palette,
tertiary: mat.$blue-palette,
),
typography: Roboto,
density: 0,
)
);
}

We will modify the theme colors in next section.

1.5 Remove usage of system-level mixins

:root {
@include mat.system-level-colors(themes.$my-app-theme);
@include mat.system-level-typography(themes.$my-app-theme);
}

1.6 Changes in button-overrides

As some properties from v18 of button-overrides mixin are deprecated in v19, we need to use the new properties. Replace code of .overrides-example with the following:

// Customizing the button appearance using overrides API
.overrides-example {
button {
@include mat.button-overrides(
(
filled-container-color: #00ff00,
protected-container-color: #00ff00,
filled-container-height: 64px,
outlined-container-height: 64px,
protected-container-height: 64px,
text-container-height: 64px,
filled-container-shape: 32px,
outlined-container-shape: 32px,
protected-container-shape: 32px,
text-container-shape: 32px,
filled-label-text-color: orange,
outlined-label-text-color: orange,
protected-label-text-color: orange,
text-label-text-color: orange,
filled-ripple-color: #ff0000,
protected-ripple-color: #ff0000,
outlined-ripple-color: #ff0000,
text-ripple-color: #ff0000,
outlined-outline-color: #0000ff,
)
);
}
}

2. Updates in dark theme

We will make similar changes in dark theme file at src/styles/themes/dark.scss.

2.1 Remove redundant mixin usages

.dark-theme {
@include mat.elevation-classes();
@include mat.app-background();
}

2.2 Remove individual component colors

.dark-theme {
@include mat.button-color(themes.$my-app-dark-theme);
@include mat.icon-color(themes.$my-app-dark-theme);
@include mat.menu-color(themes.$my-app-dark-theme);
@include mat.form-field-color(themes.$my-app-dark-theme);
@include mat.input-color(themes.$my-app-dark-theme);
}

2.3 Use color-scheme

.dark-theme {
color-scheme: dark;
}

2.4 Remove usage of system-level mixins

.dark-theme {
@include mat.system-level-colors(themes.$my-app-dark-theme);
@include mat.system-level-typography(themes.$my-app-dark-theme);
}

3. Custom component style changes

3.1 Changes in component styles barrel file

Let’s clean up the barrel file at src/styles/components/_index.scss and keep only single line:

@forward "../../app/shared/components/alert/alert-theme.css";

3.2 Remove usage of theme mixin

Remove usage of components.theme mixin from src/styles.scss and src/styles/themes/dark.scss files.

3.3 Using correct tokens

Simply find --sys and replace it with --mat-sys in whole project.

4. Changes for custom theme

We will make changes in src/styles/themes/_custom-theme.scss file.

4.1 Remove usage of define-theme function

$custom-theme: mat.define-theme(
(
color: (
primary: mat.$rose-palette,
tertiary: mat.$red-palette,
use-system-variables: false,
),
typography: (
plain-family: sans-serif,
brand-family: monospace,
use-system-variables: false,
),
density: (
scale: -3,
),
)
);

4.2 Remove component themes

.custom-theme {
@include mat.button-color($custom-theme);
@include mat.button-typography($custom-theme);
@include mat.button-density($custom-theme);
}

4.3 Use new theme mixin

.custom-theme {
@include mat.theme(
(
color: (
primary: mat.$rose-palette,
tertiary: mat.$red-palette,
),
typography: (
plain-family: sans-serif,
brand-family: monospace,
),
density: -3,
)
);
}

5. Remove usage of M3 theme file

We want to remove usage of m3-theme.scss file.

  1. Delete m3-theme.scss file.
  2. Delete src/styles/themes/_all.scss file.

6. Create and use new palette file

6.1 Create new palette file

We will create new palette file at src/styles/themes/.

Terminal window
ng generate @angular/material:theme-color --primary-color 6750a4 --directory src/styles/themes/ --interactive false

6.2 Use new palette file

We will use this palette in src/styles.scss file.

@use "./styles/themes/theme-colors";
:root {
@include mat.theme(
(
color: (
primary: mat.$azure-palette,
primary: theme-colors.$primary-palette,
tertiary: mat.$blue-palette,
tertiary: theme-colors.$tertiary-palette,
),
typography: Roboto,
density: 0,
)
);
}
6.2.1 Changes for button color variants

For button color variants, we need to remove usage of button-color mixin and use theme-overrides mixin instead. Note that buttons in Angular Material relies heavily on primary color, so we need to simply override it.

@each $variant in $color-variants {
.mat-#{$variant} {
@include mat.button-color(themes.$my-app-theme, $color-variant: $variant);
@include mat.theme-overrides(
(
primary: var(--mat-sys-#{$variant}),
on-primary: var(--mat-sys-on-#{$variant}),
)
);
}
}

Changes for color picker

If you change the color from color picker, you will see that the colors are not updated on the UI. This is because the color picker generates CSS variables with --sys prefix, but we are using --mat-sys prefix in our project.

We need to update the color picker to use --mat-sys prefix. Simply add below at the end of generateDynamicTheme function in src/app/shared/components/color-picker/color-picker.component.ts:

color-picker.component.ts
generateDynamicTheme(isDark?: boolean) {
// rest remains same
const styles = targetElement.style;
for (const key in styles) {
if (Object.prototype.hasOwnProperty.call(styles, key)) {
const propName = styles[key];
if (propName.indexOf('--md-sys') === 0) {
const sysPropName =
'--mat-sys' + propName.replace('--md-sys-color', '');
targetElement.style.setProperty(
sysPropName,
targetElement.style.getPropertyValue(propName)
);
}
}
}
}

Changes for density

As of Angular Material 19.1, there is no API available from which we can get density. So, we need to manually pass the density value to alert component.

Let’s clean up src/app/shared/components/alert/_alert-theme.scss file, and keep only below content:

_alert-theme.scss
@use "sass:map";
@use "@angular/material" as mat;
@mixin density($density) {
$spacing: (
0: 16px,
-1: 12px,
-2: 10px,
-3: 8px,
-4: 6px,
-5: 4px,
);
$scale-spacing: map.get($spacing, $density);
.alert {
padding: $scale-spacing;
margin-bottom: $scale-spacing;
hr {
margin: $scale-spacing 0;
}
}
}

Next, add forward this file from src/styles/components/_index.scss file.

components/_index.scss
@forward "../../app/shared/components/alert/alert-theme.css";
@forward "../../app/shared/components/alert/alert-theme" as alert-theme-*;

Lastly, go to main styles file at src/styles.scss and update the code include alert-theme-density mixin.

styles.scss
// rest remains same
:root {
$density: 0;
@include mat.theme(
(
color: (
primary: theme-colors.$primary-palette,
tertiary: theme-colors.$tertiary-palette,
),
typography: Roboto,
density: 0,
density: $density,
)
);
@include components.alert-theme-density($density);
}

Summary of changes for Angular Material Theming API

#Old APINew API
1mat.define-theme functionmat.theme mixin
2mat.get-theme-color function--mat-sys-<color> system variable
2.1 (Example)color: mat.get-theme-color($theme, primary);color: var(--mat-sys-primary);
2.2 (Example)color: mat.get-theme-color($theme, on-primary-container);color: var(--mat-sys-on-primary-container);
3mat.get-theme-typography function--mat-sys-<level>-<size>-<token> system variable
3.1 (Example)font: mat.get-theme-typography($theme, "display-large");font: var(--mat-sys-display-large);
3.2 (Example)letter-spacing: mat.get-theme-typography($theme, "body-medium", "letter-spacing");letter-spacing: var(--mat-sys-body-medium-tracking);
4mat.get-theme-density functionNo equivalent new API, manually pass density
5mat.typography-hierarchy mixinStill available in new API, but not recommended to use. Instead, manually use typography system variables.