EmotionTechテックブログ

株式会社エモーションテックのProduct Teamのメンバーが、日々の取り組みや技術的なことを発信していくブログです。

Angular Material を v18 に update してみた

こんにちは!フロントエンドエンジニアの高橋 a.k.a 黄色い人( @fusho_takahashi )です。

Angular Material は v18 で大幅なアップデートがありました。ついに Material 3 が stable になったのです 🎉 このアップデートは v15 で MDC-based components が stable になったときのような、Angular Material にとってはかなり重要で大きなアップデートといえます。

今回は v17 の Material 2 ベースのアプリを v18 に ng update すると何が変わるのか。theme の設定を中心にご紹介します。

v17 でアプリケーションを作成する

まず、今回このような単純なアプリケーションを用意します。

HERO HEADER と書いてあるヘッダー + 各 theme color のボタンを並べてみました。

theme 設定

今回は ng add @angular/material をするとき、theme 設定で custom を選択すると作成される設定をそのまま使用しています。

@use "@angular/material" as mat;
@include mat.core();

$my-app-primary: mat.define-palette(mat.$indigo-palette);
$my-app-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$my-app-warn: mat.define-palette(mat.$red-palette);

$my-app-theme: mat.define-light-theme(
  (
    color: (
      primary: $my-app-primary,
      accent: $my-app-accent,
      warn: $my-app-warn,
    ),
    typography: mat.define-typography-config(),
    density: 0,
  )
);

@include mat.all-component-themes($my-app-theme);

Hero Header

ヘッダー部分は HeroHeaderComponent として別 component になっており、_hero-header-theme.scss を作成して theme の色やフォント設定を反映しています。

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

// theme カラーを文字色に適用
@mixin color($theme) {
  $color-config: mat.get-color-config($theme);
  $primary-palette: map.get($color-config, "primary");

  header {
    color: mat.get-color-from-palette($primary-palette, 500);
  }
}


// theme に設定されている font-family・font-size・line-height を適用
@mixin typography($theme) {
  $typography-config: mat.get-typography-config($theme);

  header{
    font-family: mat.font-family($typography-config);
    font-size: mat.font-size($typography-config, "headline-1");
    line-height: mat.line-height($typography-config, "headline-1");
  }
}


@mixin theme($theme) {
  $color-config: mat.get-color-config($theme);
  @if $color-config != null {
    @include color($theme);
  }

  $typography-config: mat.get-typography-config($theme);
  @if $typography-config != null {
    @include typography($theme);
  }
}

Buttons

Button は色が分かりやすいように mat-flat-button を使用し、それぞれ color 属性に theme の色の名前を渡しています。

  <button mat-flat-button color="primary">Primary</button>
  <button mat-flat-button color="accent">Accent</button>
  <button mat-flat-button color="warn">Warn</button>
  <button mat-flat-button [disabled]>Disabled</button>

v18 にアップデートする

公式の Update Guide の通りアップデートしていきましょう。

ng update @angular/core@18 @angular/cli@18
ng update @angular/material@18

これで v18 になりました。

v18 になって何が変わったか

さすが Angular、アップデートしたのに表示は画像比較しても何も変わっていません。 しかし内部はけっこう変わっているんです。

theme 設定

Angular Material は v18 からデフォルトが Material 3 の theme になっており、v17 まで使われていた Material 2 に関する scss 関数・変数は、すべて m2- という prefix が付けられるようになりました。update コマンドによって style.scss は下記のように変更されます。

@use "@angular/material" as mat;

@include mat.core();

$my-app-primary: mat.m2-define-palette(mat.$m2-indigo-palette);
$my-app-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400);
$my-app-warn: mat.m2-define-palette(mat.$m2-red-palette);

$my-app-theme: mat.m2-define-light-theme(
  (
    color: (
      primary: $my-app-primary,
      accent: $my-app-accent,
      warn: $my-app-warn,
    ),
    typography: mat.m2-define-typography-config(),
    density: 0,
  )
);

@include mat.all-component-themes($my-app-theme);

全ての component に theme を適用する all-component-themes() 関数は m2- の prefix がついておらず、Material2 と Material 3 の theme 設定どちらでも引数として渡すことができます。 なぜバージョンをまたいだ設定を渡せるかというと、今回から theme 設定に version を持つことになったからです。

theme version Material Design version
0 Material 2
1 Material 3

もし Material 2 の theme と Material 3 の theme を両方使用できる component を作りたい場合、上記のように theme の version は Material Design の version と一致しないことに注意しましょう。

Hero Header

style.scss 以外の _hero-header-theme.scss のようなファイルも update コマンドで変更してくれるようです。こちらも同様に m2- の prefix が付きます。

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

@mixin color($theme) {
  $color-config: mat.m2-get-color-config($theme);
  $primary-palette: map.get($color-config, "primary");

  .header {
    color: mat.m2-get-color-from-palette($primary-palette, 500);
  }
}

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

  .header {
    font-family: mat.m2-font-family($typography-config);
    font-size: mat.m2-font-size($typography-config, "headline-1");
    line-height: mat.m2-line-height($typography-config, "headline-1");
  }
}

@mixin theme($theme) {
  $color-config: mat.m2-get-color-config($theme);
  @if $color-config != null {
    @include color($theme);
  }

  $typography-config: mat.m2-get-typography-config($theme);
  @if $typography-config != null {
    @include typography($theme);
  }
}

Buttons

ボタンに関しては何も変わっていませんが、変わらずきちんと色の指定が反映されています。

まとめ・感想

Angular Material にとって大きなアップデートとなった v18。既存の scss 関数・変数は prefix をつけて新たな関数と分ける方針となりましたが、update コマンドのおかげで自動的にマイグレーションしてくれました。

まだ Material 2 が将来 deprecated になるかどうかも分かりませんが、今回はだいぶデザインが変わっているので、もし Material 3 ベースに変更する必要が出てきた場合は、v15 のときに比べてめちゃくちゃ大変そうです。 Material 3 にワクワクしつつも、作成済みの Material 2 の component が 大量にあるのが現状です。Material 2 をサポートしていただいている間に、しっかりとMaterial 3 への移行計画を立てたいと思います!