cssangularsassangular-materialmaterial3

Setting Mat-Button color in Angular Material 19 (M3)


I'm using angular material 19.0.3 and the m3 theming mechanism here's my style.scss

html {
  color-scheme: light dark;
  @include mat.theme((color: (
        primary: ft-green-theme.$primary-palette,
        tertiary: ft-green-theme.$tertiary-palette,
      ),
      typography: InterVariable,
      density: 0));

  &[dir='rtl'] {
    @include mat.theme((typography: IranSans,
      ));
  }
}

body.light {
  color-scheme: light;
}

body.dark {
  color-scheme: dark;
}

Now I have a button

<button mat-flat-button >click me</button>

I used to be able to do this

<button mat-flat-button color='danger'>click me</button>

and the button would be red.

But in the new version of angular material (19) they've changed things. I tried to read the documentation but I don't understand a thing.

In mat-button documentation it says:

Theme color of the button. This API is supported in M2 themes only, it has no effect in M3 themes.

For information on applying color variants in M3, see https://material.angular.io/guide/theming#using-component-color-variants.

And in the link provided there's just an explanation about how to give a color pallette as a theme.

But suppose, I'm gonna have a confirmation dialog and the yes button will be green and the cancel button will be red.

How am I supposed to color individual mat-buttons in angular material 19??


Solution

  • When you use @include mat.theme(...) everything is taken care of internally, so there is no way to access the theme (to my knowledge) so you need to set the overrides manually using @include mat.button-overrides(( ... )).

    This method could be a problem, since you just want to theme the button based on whether it's primary, secondary, etc.


    As far as I know, the available options of types are 'primary', 'secondary', 'tertiary', 'error'.

    We can define our own theme button by using mat.button-color, this mixin takes two arguments.

    /// Outputs color theme styles for the mat-button.
    /// @param {Map} $theme The theme to generate color styles for.
    /// @param {ArgList} Additional optional arguments (only supported for M3 themes):
    ///   $color-variant: The color variant to use for the button: primary, secondary, tertiary,
    ///      or error (If not specified, default primary color will be used).
    @mixin color($theme, $options...) {
    

    The first is the theme, but when we use @include mat.theme(...) we do not have this theme stored in a SCSS property, hence we can use the previous method of using mat.define-theme, Which provides the theme for use to customize.

    $theme: mat.define-theme(
      (
        color: (
          theme-type: light,
          primary: mat.$azure-palette,
          tertiary: mat.$magenta-palette,
        ),
        density: (
          scale: 0,
        ),
      )
    );
    

    After this, it is simply a matter of inputting this theme to the function and setting the color variant.

    body {
      font-family: Roboto, 'Helvetica Neue', sans-serif;
      margin: 0;
      padding: 30px;
      height: 100%;
      @include mat.all-component-themes($theme);
    
      .primary {
        @include mat.button-color($theme: $theme, $color-variant: 'primary');
      }
    
      .secondary {
        @include mat.button-theme($theme: $theme, $color-variant: 'secondary');
      }
    
      .tertiary {
        @include mat.button-theme($theme: $theme, $color-variant: 'tertiary');
      }
    
      .error {
        @include mat.button-theme($theme: $theme, $color-variant: 'error');
      }
    }
    

    Full Code:

    SCSS:

    @use '@angular/material' as mat;
    
    $theme: mat.define-theme(
      (
        color: (
          theme-type: light,
          primary: mat.$azure-palette,
          tertiary: mat.$magenta-palette,
        ),
        density: (
          scale: 0,
        ),
      )
    );
    
    body {
      font-family: Roboto, 'Helvetica Neue', sans-serif;
      margin: 0;
      padding: 30px;
      height: 100%;
      @include mat.all-component-themes($theme);
    
      .primary {
        @include mat.button-color($theme: $theme, $color-variant: 'primary');
      }
    
      .secondary {
        @include mat.button-theme($theme: $theme, $color-variant: 'secondary');
      }
    
      .tertiary {
        @include mat.button-theme($theme: $theme, $color-variant: 'tertiary');
      }
    
      .error {
        @include mat.button-theme($theme: $theme, $color-variant: 'error');
      }
    }
    
    html {
      height: 100%;
    }
    
    @include mat.typography-hierarchy($theme);
    

    TS:

    import { Component } from '@angular/core';
    import { MatIconModule } from '@angular/material/icon';
    import { MatDividerModule } from '@angular/material/divider';
    import { MatButtonModule } from '@angular/material/button';
    import { CommonModule } from '@angular/common';
    
    /**
     * @title Basic buttons
     */
    @Component({
      selector: 'button-overview-example',
      templateUrl: 'button-overview-example.html',
      styleUrl: 'button-overview-example.css',
      imports: [MatButtonModule, MatDividerModule, MatIconModule, CommonModule],
    })
    export class ButtonOverviewExample {
      types = ['primary', 'secondary', 'tertiary', 'error'];
    }
    

    HTML:

    @for(type of types; track $index) {
    <section>
      <div class="example-label">Basic {{type}}</div>
      <div class="example-button-row">
        <button mat-button [ngClass]="type">Basic</button>
        <button mat-button disabled [ngClass]="type">Disabled</button>
        <a
          mat-button
          href="https://www.google.com/"
          target="_blank"
          [ngClass]="type"
          >Link</a
        >
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Raised {{type}}</div>
      <div class="example-button-row">
        <button mat-raised-button [ngClass]="type">Basic</button>
        <button mat-raised-button disabled [ngClass]="type">Disabled</button>
        <a
          mat-raised-button
          href="https://www.google.com/"
          target="_blank"
          [ngClass]="type"
          >Link</a
        >
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Stroked {{type}}</div>
      <div class="example-button-row">
        <button mat-stroked-button [ngClass]="type">Basic</button>
        <button mat-stroked-button disabled [ngClass]="type">Disabled</button>
        <a
          mat-stroked-button
          href="https://www.google.com/"
          target="_blank"
          [ngClass]="type"
          >Link</a
        >
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Flat {{type}}</div>
      <div class="example-button-row">
        <button mat-flat-button [ngClass]="type">Basic</button>
        <button mat-flat-button disabled [ngClass]="type">Disabled</button>
        <a
          mat-flat-button
          href="https://www.google.com/"
          target="_blank"
          [ngClass]="type"
          >Link</a
        >
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Icon {{type}}</div>
      <div class="example-button-row">
        <div class="example-flex-container">
          <button
            mat-icon-button
            aria-label="Example icon button with a vertical three dot icon"
            [ngClass]="type"
          >
            <mat-icon>more_vert</mat-icon>
          </button>
          <button
            mat-icon-button
            disabled
            aria-label="Example icon button with a open in new tab icon"
            [ngClass]="type"
          >
            <mat-icon>open_in_new</mat-icon>
          </button>
        </div>
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">FAB {{type}}</div>
      <div class="example-button-row">
        <div class="example-flex-container">
          <div class="example-button-container">
            <button
              mat-fab
              aria-label="Example icon button with a delete icon"
              [ngClass]="type"
            >
              <mat-icon>delete</mat-icon>
            </button>
          </div>
          <div class="example-button-container">
            <button
              mat-fab
              disabled
              aria-label="Example icon button with a heart icon"
              [ngClass]="type"
            >
              <mat-icon>favorite</mat-icon>
            </button>
          </div>
        </div>
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Mini FAB {{type}}</div>
      <div class="example-button-row">
        <div class="example-flex-container">
          <div class="example-button-container">
            <button
              mat-mini-fab
              aria-label="Example icon button with a menu icon"
              [ngClass]="type"
            >
              <mat-icon>menu</mat-icon>
            </button>
          </div>
          <div class="example-button-container">
            <button
              mat-mini-fab
              disabled
              [ngClass]="type"
              aria-label="Example icon button with a home icon"
            >
              <mat-icon>home</mat-icon>
            </button>
          </div>
        </div>
      </div>
    </section>
    }
    <mat-divider></mat-divider>
    @for(type of types; track $index) {
    <section>
      <div class="example-label">Extended Fab {{type}}</div>
      <div class="example-button-row">
        <div class="example-flex-container">
          <div class="example-button-container">
            <button mat-fab extended [ngClass]="type">
              <mat-icon>favorite</mat-icon>
              Basic
            </button>
          </div>
          <div class="example-button-container">
            <button mat-fab extended disabled [ngClass]="type">
              <mat-icon>favorite</mat-icon>
              Disabled
            </button>
          </div>
          <div class="example-button-container">
            <a mat-fab extended routerLink="." [ngClass]="type">
              <mat-icon>favorite</mat-icon>
              Link
            </a>
          </div>
        </div>
      </div>
    </section>
    }
    

    Stackblitz Demo