Exploring Material 3 Design With Angular Material
In this article, we will explore Material 3 design integration with Angular Material.
Angular Material team is soon going to roll out the stable usage of it's Material 3 (M3) integration. This integration is already part of it's next
major release.
In this article, we are going to use the yet to be released 18
(or next
) version of Angular, Angular CLI and Angular Material. The goal of this article is to give a quick idea about what is coming up with Angular Material in it's next major release.
Creating a v18
Angular Project
npx @angular/cli@next new angular-material-3
Then select Sass (SCSS)
for styling and No
for SSR/SSG/Prerendering
.
? Which stylesheet format would you like to use? Sass (SCSS) [ https://sass-lang.com/documentation/syntax#scss ]
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No
And lastly, move into the project folder:
cd angular-material-3
Adding Angular Material v18
Let's add @angular/material
into the newly created project:
ng add @angular/material@next
And select answers as below:
? Choose a prebuilt theme name, or "custom" for a custom theme: Custom
? Set up global Angular Material typography styles? Yes
? Include the Angular animations module? Include and enable animations
New M3 Themes
When selecting the theme, notice that now we are getting options of new themes:
Theme Name |
Rose & Red |
Azure & Blue |
Magenta & Violet |
Cyan & Orange |
These are new themes created by Angular Material team to be compatible to M3.
If you have selected Custom, your styles.scss
would look like below:
@use "@angular/material" as mat;
@include mat.core();
$angular-material-3-theme: mat.define-theme(
(
color: (
theme-type: light,
primary: mat.$azure-palette,
tertiary: mat.$blue-palette,
),
density: (
scale: 0,
),
)
);
:root {
@include mat.all-component-themes($angular-material-3-theme);
}
The syntax is almost similar to what it was in Material 2 (M2) integration with Angular Material. But, notice the usage of new palettes. We are using $azure-palette
and $blue-palette
. Below are all new palettes introduced in M3 integration with Angular Material, that can be used with the primary
and tertiary
options:
$red-palette
$green-palette
$blue-palette
$yellow-palette
$cyan-palette
$magenta-palette
$orange-palette
$chartreuse-palette
$azure-palette
$violet-palette
$rose-palette
Creating basic app
Let's create a simple application to see and understand basic usages of updated SASSmixins
for M3 in Angular Material.
We are going to use Angular Material Schematics to generate components:
ng generate @angular/material:navigation layout
ng generate @angular/material:dashboard dashboard
ng generate @angular/material:address-form address-form
ng generate @angular/material:table table
ng generate @angular/material:tree tree
ng generate @angular/material:drag-drop drag-drop
Updating layout
Go to src/app/layout/layout.component.html
and add <ng-content>
in <mat-sidenav-content>
like below:
<mat-sidenav-content>
<!--mat-toolbar remains same-->
<div class="sidenav-scroll-wrapper">
<div class="sidenav-content">
<ng-content></ng-content>
</div>
</div>
</mat-sidenav-content>
Next, let's add and modify some styling in src/app/layout/layout.component.scss
so that sidenav content looks more M3 oriented:
.sidenav-container {
height: 100%;
}
.sidenav {
width: 240px;
padding: 0 8px;
box-sizing: border-box;
}
.mat-toolbar.mat-primary {
position: sticky;
top: 0;
z-index: 1;
}
mat-sidenav-content {
padding-right: 16px;
}
.sidenav-scroll-wrapper {
height: calc(100dvh - 64px - 16px);
overflow: auto;
border-radius: 16px;
box-sizing: border-box;
}
.sidenav-content {
max-height: 100%;
overflow-y: auto;
padding: 16px;
box-sizing: border-box;
@media (pointer: fine) {
&::-webkit-scrollbar {
background-color: transparent;
width: 8px;
}
&::-webkit-scrollbar-thumb {
border-radius: 4px;
}
}
}
@media (max-width: 959.98px) {
mat-sidenav-content {
padding-right: 8px;
padding-left: 8px;
}
.sidenav-scroll-wrapper {
height: calc(100dvh - 64px);
}
.sidenav-content {
overflow-y: visible;
padding: 8px;
}
}
Using layout
Now, simply go to src/app/app.component.html
and update it's content with below:
<app-layout>
<router-outlet />
</app-layout>
Also, don't forget to import LayoutComponent
in src/app/app.component.ts
.
At this point, the output looks like below:
Let's add some colors in the content area so that it's easy to distinguish.
Theming layout
Create a file src/app/layout/_layout-component.theme.scss
with below content:
@use "@angular/material" as mat;
@mixin theme($theme) {
.sidenav-scroll-wrapper {
background-color: rgba(mat.get-theme-color($theme, primary-container), 0.75);
}
.sidenav-content {
@media (pointer: fine) {
&::-webkit-scrollbar-thumb {
background-color: mat.get-theme-color($theme, primary);
}
}
}
}
Notice the usages of get-theme-color
mixin:
To get color of the
primary-container
role, we usedmat.get-theme-color($theme, primary-container)
To get color from tonal palette, we used
mat.get-theme-color($theme, primary)
.
To learn more, checkout Reading tonal palette colors and Reading color roles.
Using layout component theme
Now, include and call this mixin in main styles.scss
file:
@use "./app/layout/layout-component.theme";
:root {
@include layout-component.theme($theme);
}
Let's see the output now:
Updating routes
Go to your src/app/app.routes.ts
and update the routes:
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'dashboard',
},
{
path: 'dashboard',
loadComponent: () =>
import('./dashboard/dashboard.component').then(
(c) => c.DashboardComponent
),
title: 'Dashboard'
},
{
path: 'address',
loadComponent: () =>
import('./address-form/address-form.component').then(
(c) => c.AddressFormComponent
),
title: 'Address'
},
{
path: 'table',
loadComponent: () =>
import('./table/table.component').then(
(c) => c.TableComponent
),
title: 'Table'
},
{
path: 'tree',
loadComponent: () =>
import('./tree/tree.component').then(
(c) => c.TreeComponent
),
title: 'Tree'
},
{
path: 'drag-drop',
loadComponent: () =>
import('./drag-drop/drag-drop.component').then(
(c) => c.DragDropComponent
),
title: 'Drag-Drop'
},
];
And to load the routes, we will first update src/app/layout/layout.component.ts
:
import { RouterLink, RouterLinkActive } from '@angular/router';
@Component({
selector: 'app-layout',
// rest remains same
imports: [
// Add below imports
RouterLink,
RouterLinkActive
]
})
export class LayoutComponent {
rootRoutes = routes.filter(r=>r.path);
// rest remains same
}
Now, replace <mat-nav-list>
content with below:
<mat-nav-list>
@for (item of rootRoutes; track $index) {
<a
mat-list-item
[routerLink]="item.path"
#link="routerLinkActive"
routerLinkActive
[activated]="link.isActive"
>
{{ item.title }}
</a>
}
</mat-nav-list>
At this point the output looks like below:
Custom M3 theme
We saw in the beginning that Angular Material team provides some pre-built palettes and themes.
But, it is also possible to generate a theme based on a custom color. To do so, simply run below command:
ng generate @angular/material:m3-theme
After running the above script, your will be presented with below question:
What HEX color should be used to generate the M3 theme? It will represent your primary color palette. (ex. #ffffff)
Simply enter #6750A4
for the above question and leave blank for the rest of the questions.
The schematic will create a file called m3-theme.scss
at root. You can explore the file to understand how the theme is created:
// m3-theme.scss - content reduced for brevity
$light-theme: mat.define-theme((
color: (
theme-type: light,
primary: $_primary,
tertiary: $_tertiary,
)
));
$dark-theme: mat.define-theme((
color: (
theme-type: dark,
primary: $_primary,
tertiary: $_tertiary,
)
));
Now, you can simply use these newly created themes in main styles.scss
:
@use "../m3-theme";
:root {
@include mat.all-component-themes(m3-theme.$light-theme);
}
And the output will look like below:
Conclusion
We created a v18
Angular application. And installed @angular/material
's next
(v18
) version in it.
Then we created some boilerplate components like dashboard, address-form, tree, table and drag-drop views using Angular Material Schematics.
After creating components, we modified layout component and it's styling, and we started using it in main app component.
Lastly, we learned the usage of new schematic ng generate @angular/material:m3-theme
.
The code is available on GitHub.