EmotionTechテックブログ

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

Angular Material M2からM3へ:見た目を崩さずテーマ移行する方法

Angular Material を愛する皆さんこんにちは!フロントエンドエンジニアの高橋 a.k.a 黄色い人( @fusho_takahashi )です。 エモーションテック Advent Calendar 2024 22 日目の記事を担当させていただきます!

M2 のまま使い続ける恐怖

エモーションテックでは、UI コンポーネントライブラリとして Angular Material を使用しています。Angular Material はその名の通り、Material Design のデザインを基に作られており、本家 Material Design のバージョンアップに伴い、これまでに 2 度大きな変更が行われました。

M1 から M2 への変更では、見た目に大きな変化はなく、公式からマイグレーションガイドも提供されていました。しかし、M2からM3への変更は事情が異なります。見た目が大幅に変わったこともあり、公式見解としてM2とM3は今後もしばらく両方サポートされ続けるようです。

現在エモーションテックでは M2 の設定を採用しています。v17 時点では引き続きサポートされるとのことでしたが、いつ M2 が Mat Legacy になるか分かりません。ちなみに、私は M2 が v20 で廃止されるというアナウンスが出る夢を見て、恐怖のあまり汗だくで目覚めたことが 2 度あります笑

M3 のテーマで M2 のデザインを再現する

M2 はサポートが続けられるそうですが、私が三度目の悪夢を見る前に M3 で M2 のデザインを再現する方法を考えておきましょう。しかも!v19 から公式サイトの各コンポーネントのページに styling タブが新設されました!この styling タブで紹介されている overrides mixin を駆使して、M2 のデザインを再現していきます!

実践編:Button

とりあえず並べてみる

Angular v19 でアプリケーションを new して、Angular Material を入れて MatButton を 2 つ並べます(上: M3 下: M2)。分かりやすいように、今回は mat-flat-button を使用しています。

いやーかなり違いますね笑 これはただテーマ設定をマイグレーションしただけでは、アプリケーションの印象がガラッと変わってしまいそうです。

形を揃える

border-radius

まず角の丸さが全然違いますね。ただし styling タブを見てもそれらしい設定項目がなさそうなので、開発者ツールで見てみると --mat-sys-corner-full という css 変数を設定しているようです。 今回は button だけ変更したいので、下記のように書いて上書きします。

[mat-flat-button] {
  --mat-sys-corner-full: 4px;
}

letter-spacing

よく見るとボタン全体だけでなく、文字の横幅も違いそうです。

描画されている文字と文字の間、つまり letter-spacing の値が違うようです。styling タブでいうと filled-label-text-tracking の設定が異なっています。開発者ツールで M2 テーマの letter-spacing を見つけ出して設定します。

:root {
  @include mat.button-overrides(
    (
      filled-label-text-tracking: 0.0892857143em,
    )
  );
}

padding

文字の横幅が揃ったので、続いてボタンの横幅を揃えます。これは単純に padding を揃えればよいだけです。filled-horizontal-padding の設定を追加します。

:root {
  @include mat.button-overrides(
    (
      filled-label-text-tracking: 0.0892857143em,
      filled-horizontal-padding: 16px,
    )
  );
}

height

あと少しです!横幅は完璧に揃いましたが、横並びにしてみると高さが違うことがわかります。(左: M3 右: M2)

filled-container-height を設定しましょう

:root {
  @include mat.button-overrides(
    (
      filled-label-text-tracking: 0.0892857143em,
      filled-horizontal-padding: 16px,
      filled-container-height: 36px,
    )
  );
}

これで形は完璧に揃いました!続いて色を揃えましょう。

色を揃える

M3 用の Custom Color Palette を作成します。M3 から schematics が提供されているので、M2 の primary color を指定して作成します。

ng generate @angular/material:theme-color

_theme-colors.scss というファイルが出来上がるので、theme 設定の mixin に渡します。

@use "../theme-colors" as custom-colors;

@include mat.theme(
    (
      color: (
        theme-type: light,
        primary: custom-colors.$primary-palette,
      ),
      typography: Roboto,
      density: 0,
    )
  );

これで完璧!…いや、あれ?微妙に色が違います涙 どうやら primary color を指定してもその通りの色で palette が生成されるわけではなさそうです。M3 に合わせた色にマッピングされる仕様のようですね。惜しいところですが、大きな違いはないので今回はこれで良しとしましょう。

終わりに

Angular Material 公式サイトの各コンポーネントに styling タブができたおかげで、割とすんなり M2 のテーマを再現することができました。class をつければ簡単に M2 と M3 のテーマを分けることができるので、段階的にマイグレーションしていくのが良いかもしれません。実際に試してみたところ、少し手間はかかりましたが、それでも思ったよりはスムーズに進められ、これで悪夢を見ることもなくなりそうです!

エモーションテックでは顧客体験、従業員体験の改善をサポートし、世の中の体験を変えるプロダクトを開発しています。 プロダクトに興味のある方、Angular ・ Angular Material を使ったアプリケーション開発をしたい方、ぜひ採用ページからご応募をお願いいたします。

hrmos.co