---
description: This rule provides comprehensive best practices and coding standards for Angular development with Angular Material, focusing on Material 3 (a.k.a. M3) design, theme configuration and various API usages.
alwaysApply: false
globs: *.html,*.ts,*.scss,*.css
---

# Angular Material 20 Best Practices

This project adheres to modern Angular Material best practices, emphasizing maintainability, performance, accessibility, scalability and correct usage of APIs.

## Core Principles

### SCSS vs CSS

- **Prefer SCSS** for styling, especially when theme customization is required. Angular Material has APIs written in SCSS.
- **Use CSS only** when you need to use theme styles generated by `mat.theme` mixin. Modifications or customizations for Angular Material theming are not possible with CSS.

### Component & Directive Imports

Always import components and directives from `@angular/material` package. Avoid importing modules.

**Good:**

```ts
import { MatButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatCard, MatCardContent } from '@angular/material/card';
```

**Bad:**

```ts
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatCardModule } from '@angular/material/card';
```

## Theming Configuration

Always use `mat.theme` mixin to configure the theme. **Avoid** using `mat.define-theme`, `mat.define-light-theme`, `mat.define-dark-theme` functions and `mat.core` mixin.

### Basic Theme Configuration

The `mat.theme` mixin takes a map with the following properties:

- **`color`**: Single color palette or a map of color palettes
- **`typography`**: Single typography or a map of typography properties
- **`density`**: Integer from 0 to -5 (0 = default spacing, -5 = most dense)

### Simple Theme Example

```scss
@use '@angular/material' as mat;

html {
  color-scheme: light dark;
  @include mat.theme(
    (
      color: mat.$violet-palette,
      typography: Roboto,
      density: 0,
    )
  );
}
```

### Advanced Theme with Multiple Color Palettes

```scss
@use '@angular/material' as mat;

html {
  color-scheme: light dark;
  @include mat.theme(
    (
      color: (
        primary: mat.$violet-palette,
        tertiary: mat.$orange-palette,
      ),
      typography: (
        plain-family: Roboto,
        brand-family: Open Sans,
        bold-weight: 900,
        medium-weight: 500,
        regular-weight: 300,
      ),
      density: 0,
    )
  );
}
```

### Supporting Light and Dark Mode with Selectors

```scss
@use '@angular/material' as mat;

html {
  color-scheme: light;
  @include mat.theme(
    (
      color: mat.$violet-palette,
      typography: Roboto,
      density: 0,
    )
  );
}

body.dark-mode {
  color-scheme: dark;
}
```

### Multiple Themes

```scss
@use '@angular/material' as mat;

html {
  @include mat.theme(
    (
      color: mat.$violet-palette,
      typography: Roboto,
      density: 0,
    )
  );
}

.example-bright-container {
  @include mat.theme(
    (
      color: mat.$cyan-palette,
    )
  );
}
```

## Button Directives

Always use `matButton`, `matIconButton` & `matFab` selectors for Angular Material buttons' directives. **Avoid** using `mat-button`, `mat-raised-button`, `mat-stroked-button`, `mat-flat-button`, `mat-icon-button`, `mat-fab`, etc. selectors.

### Correct Button Usage

```html
<button matButton>Basic</button>
<button matButton="elevated">Elevated</button>
<button matButton="outlined">Outlined</button>
<button matButton="filled">Filled</button>
<button matButton="tonal">Tonal</button>
<button
  matIconButton
  aria-label="Example icon button with a vertical three dot icon">
  <mat-icon>more_vert</mat-icon>
</button>
<button matFab aria-label="Example icon button with a delete icon">
  <mat-icon>delete</mat-icon>
</button>
```

### Incorrect Button Usage (Avoid)

```html
<button mat-button>Basic</button>
<button mat-raised-button>Elevated</button>
<button mat-stroked-button>Outlined</button>
<button mat-flat-button>Filled</button>
<button mat-icon-button aria-label="Example icon button">
  <mat-icon>more_vert</mat-icon>
</button>
<button mat-fab aria-label="Example icon button">
  <mat-icon>delete</mat-icon>
</button>
```

## Using Theme Styles & System Variables

The `mat.theme` mixin emits CSS variables known as "System Variables" that can be used to style components.

### Basic Usage Example

```css
:host {
  background: var(--mat-sys-primary-container);
  color: var(--mat-sys-on-primary-container);
  border: 1px solid var(--mat-sys-outline-variant);
  font: var(--mat-sys-body-large);
}
```

### System Variables Reference

#### Colors

- `--mat-sys-primary`, `--mat-sys-on-primary`, `--mat-sys-primary-container`, `--mat-sys-on-primary-container`
- `--mat-sys-secondary`, `--mat-sys-tertiary`, and their `on-` and `container` variants
- `--mat-sys-surface`, `--mat-sys-on-surface`, `--mat-sys-surface-container`
- `--mat-sys-error`, `--mat-sys-on-error`, `--mat-sys-error-container`
- `--mat-sys-outline`, `--mat-sys-outline-variant`

#### Typography

- `--mat-sys-display-small`, `--mat-sys-display-medium`, `--mat-sys-display-large`
- `--mat-sys-headline-small`, `--mat-sys-title-medium`, `--mat-sys-body-large`
- `--mat-sys-label-medium`, etc.

#### Shape (Border Radius)

- `--mat-sys-corner-extra-small`, `--mat-sys-corner-medium`, `--mat-sys-corner-large`, etc.

#### Elevation (Shadow)

- `--mat-sys-level0` through `--mat-sys-level5`

See [Angular Material docs](https://material.angular.dev/guide/system-variables) for a full list.

## Customizing Tokens

Angular Material components allow for narrowly targeted customization through the `overrides` mixins.

### System Token Overrides

Use `mat.theme-overrides` mixin to change system-level tokens:

```scss
@use '@angular/material' as mat;

html {
  color-scheme: light dark;
  @include mat.theme(
    (
      color: mat.$violet-palette,
      typography: Roboto,
      density: 0,
    )
  );

  .example-orange-primary-container {
    @include mat.theme-overrides(
      (
        primary-container: #84ffff,
      )
    );
  }
}
```

### Multiple System Overrides

```scss
@use '@angular/material' as mat;

.example-container {
  @include mat.theme-overrides(
    (
      primary: #ebdcff,
      on-primary: #230f46,
      body-medium: 500 1.15rem/1.3rem Arial,
      corner-large: 32px,
      level3: 0 4px 6px 1px var(--mat-sys-surface-dim),
    )
  );
}
```

### Component Token Overrides

Each Angular Material component defines an `overrides` mixin for customizing tokenized styles:

```scss
html {
  @include mat.card-overrides(
    (
      elevated-container-color: red,
      elevated-container-shape: 32px,
      title-text-size: 2rem,
    )
  );
}
```

### When to Use Which Mixin

| Mixin                       | Use Case                                                                     | Ideal Usage Count                          |
| --------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------ |
| `mat.theme`                 | Theme for application                                                        | 1                                          |
| `mat.theme-overrides`       | Change system-level tokens (e.g., success theme with green color)            | Equals to contextual themes in application |
| `mat.<COMPONENT>-overrides` | Change component-level tokens (e.g., emphasis button colors for new feature) | As and when needed                         |

## Typography Binding to HTML Elements

By default, Angular Material doesn't bind typescale levels to HTML elements, but here are recommended bindings:

| Typescale Level | Size     | Native Element |
| --------------- | -------- | -------------- |
| `display`       | `large`  | `<h1>`         |
| `display`       | `medium` | `<h2>`         |
| `display`       | `small`  | `<h3>`         |
| `headline`      | `large`  | `<h4>`         |
| `headline`      | `medium` | `<h5>`         |
| `headline`      | `small`  | `<h6>`         |

## CSS Classes

Avoid applying CSS classes to inner components/elements of Angular Material components. If needed, wrap them in a container and apply classes to container.

For example, avoid doing this:

```html
<button matButton class="flex items-center gap-2">
  <mat-icon class="ml-1">add</mat-icon>
  Add
</button>
```

Instead, do this:

```html
<button matButton>
  <mat-icon>add</mat-icon>
  Add
</div>
```

## SVGs vs mat-icons

Try to use `mat-icon` for icons that are part of the Material Design icon set. For other icons, use `MatIconRegistry` to register the icon and use it in the template using `svgIcon` attribute.

```angular-ts
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';

const ICON = `SVG Icon HTML string`;

constructor(private matIconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) {
  this.matIconRegistry.addSvgIconLiteral('custom-icon', this.sanitizer.bypassSecurityTrustHtml(ICON));
}
```

```angular-html
<mat-icon svgIcon="custom-icon"></mat-icon>
```

## Best Practices Summary

1. **Always use `mat.theme` mixin** for theme configuration
2. **Import components and directives**, not modules
3. **Use new button directive syntax** (`matButton`, `matIconButton`, `matFab`)
4. **Leverage system variables** for consistent styling
5. **Use override mixins** for targeted customization
6. **Prefer SCSS** for theme-related styling
7. **Include `color-scheme` property** for proper light/dark mode support
8. **Never override styles by targeting internal class names.**
