angular-material

Angular Material Component Library Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "angular-material" with this command: npx skills add 7spade/black-tortoise/7spade-black-tortoise-angular-material

Angular Material Component Library Skill

Rules

Setup and Configuration

  • Must install @angular/material , @angular/cdk , @angular/animations

  • Must configure provideAnimations() in app.config.ts

  • Must import specific Material modules (e.g., MatButtonModule , MatIconModule )

  • Must NOT import all Material modules with wildcard (import * as Material )

Form Controls

  • Must wrap all matInput in <mat-form-field> with <mat-label>

  • Must use appearance="outline" or appearance="fill" for form fields

  • Must use Reactive Forms with Material form controls

  • Must provide validation error messages with <mat-error>

  • Must use MatDatepickerModule with MatNativeDateModule for date pickers

Navigation Components

  • Must set explicit height on <mat-sidenav-container>

  • Must use mat-nav-list for navigation lists with @for and track

  • Must use color attribute for semantic styling (primary , accent , warn )

Buttons and Icons

  • Must use appropriate button variant: mat-button , mat-raised-button , mat-flat-button , mat-stroked-button , mat-icon-button , mat-fab , mat-mini-fab

  • Must provide aria-label for icon-only buttons

  • Must import Material Icons font in index.html

Data Tables

  • Must define displayedColumns for table columns

  • Must use matColumnDef , mat-header-cell , mat-cell for column definition

  • Must use MatSort directive with mat-sort-header for sorting

  • Must set dataSource.sort and dataSource.paginator in ngAfterViewInit()

  • Must use MatPaginator with [pageSize] and [pageSizeOptions]

Dialogs and Popups

  • Must inject MatDialog service to open dialogs

  • Must use <h2 mat-dialog-title> , <mat-dialog-content> , <mat-dialog-actions> structure

  • Must use [mat-dialog-close] for dialog action buttons

  • Must configure dialog width in open options

  • Must subscribe to afterClosed() for dialog results

Theming

  • Must use @use '@angular/material' as mat in SCSS

  • Must define custom palettes with mat.define-palette()

  • Must create theme with mat.define-light-theme() or mat.define-dark-theme()

  • Must include @include mat.all-component-themes($theme)

Accessibility

  • Must provide labels for all form fields

  • Must add ARIA attributes for icon-only buttons

  • Must ensure keyboard navigation support

  • Must use semantic color attributes (primary , accent , warn )

Performance

  • Must import only needed Material modules

  • Must use @defer for lazy loading heavy components

  • Must use virtual scrolling for large lists

Context

Summary

Angular Material is the official Material Design component library for Angular, providing 50+ production-ready components with built-in accessibility, theming, and TypeScript support.

When to Use This Skill

  • Building Angular applications with Material Design

  • Implementing forms with Material form controls

  • Creating data tables with sorting, pagination, and filtering

  • Building navigation with Material sidenav and toolbars

  • Implementing dialogs, snackbars, and bottom sheets

  • Using Material icons and buttons

  • Creating custom themes

  • Ensuring accessibility compliance

Installation

Using Angular CLI (recommended)

ng add @angular/material

Or using npm/pnpm

pnpm install @angular/material @angular/cdk @angular/animations

Application Setup

// app.config.ts (Angular 20+ standalone) import { provideAnimations } from '@angular/platform-browser/animations';

export const appConfig: ApplicationConfig = { providers: [ provideAnimations(), // ... other providers ] };

Component Import Example

// In standalone component import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatToolbarModule } from '@angular/material/toolbar';

@Component({ selector: 'app-header', standalone: true, imports: [MatButtonModule, MatIconModule, MatToolbarModule], template: &#x3C;mat-toolbar color="primary"> &#x3C;span>My App&#x3C;/span> &#x3C;span class="spacer">&#x3C;/span> &#x3C;button mat-icon-button> &#x3C;mat-icon>menu&#x3C;/mat-icon> &#x3C;/button> &#x3C;/mat-toolbar> }) export class HeaderComponent {}

📚 Core Component Categories

  1. Form Controls

Input & Text Fields:

import { MatInputModule } from '@angular/material/input'; import { MatFormFieldModule } from '@angular/material/form-field'; import { FormControl, ReactiveFormsModule } from '@angular/forms';

@Component({ standalone: true, imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule], template: &#x3C;mat-form-field appearance="outline"> &#x3C;mat-label>Email&#x3C;/mat-label> &#x3C;input matInput [formControl]="email" placeholder="user@example.com"> &#x3C;mat-hint>Enter your email address&#x3C;/mat-hint> @if (email.hasError('email')) { &#x3C;mat-error>Invalid email format&#x3C;/mat-error> } &#x3C;/mat-form-field> }) export class EmailInputComponent { email = new FormControl('', [Validators.required, Validators.email]); }

Select & Autocomplete:

import { MatSelectModule } from '@angular/material/select'; import { MatAutocompleteModule } from '@angular/material/autocomplete';

// Select example <mat-form-field> <mat-label>Country</mat-label> <mat-select [formControl]="country"> @for (country of countries; track country.code) { <mat-option [value]="country.code">{{ country.name }}</mat-option> } </mat-select> </mat-form-field>

// Autocomplete example <mat-form-field> <mat-label>Search</mat-label> <input matInput [formControl]="search" [matAutocomplete]="auto"> <mat-autocomplete #auto="matAutocomplete"> @for (option of filteredOptions(); track option) { <mat-option [value]="option">{{ option }}</mat-option> } </mat-autocomplete> </mat-form-field>

Checkboxes & Radio Buttons:

import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatRadioModule } from '@angular/material/radio';

// Checkbox <mat-checkbox [formControl]="agreeToTerms"> I agree to terms and conditions </mat-checkbox>

// Radio group <mat-radio-group [formControl]="selectedOption"> <mat-radio-button value="option1">Option 1</mat-radio-button> <mat-radio-button value="option2">Option 2</mat-radio-button> </mat-radio-group>

Date & Time Pickers:

import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatNativeDateModule } from '@angular/material/core';

<mat-form-field> <mat-label>Choose a date</mat-label> <input matInput [matDatepicker]="picker" [formControl]="selectedDate"> <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>

  1. Navigation Components

Toolbar:

import { MatToolbarModule } from '@angular/material/toolbar';

<mat-toolbar color="primary"> <button mat-icon-button> <mat-icon>menu</mat-icon> </button> <span>Application Title</span> <span class="spacer"></span> <button mat-icon-button> <mat-icon>account_circle</mat-icon> </button> </mat-toolbar>

Sidenav:

import { MatSidenavModule } from '@angular/material/sidenav';

<mat-sidenav-container class="sidenav-container"> <mat-sidenav #sidenav mode="side" opened> <mat-nav-list> @for (item of navItems; track item.route) { <a mat-list-item [routerLink]="item.route"> <mat-icon>{{ item.icon }}</mat-icon> {{ item.label }} </a> } </mat-nav-list> </mat-sidenav>

<mat-sidenav-content> <router-outlet></router-outlet> </mat-sidenav-content> </mat-sidenav-container>

Tabs:

import { MatTabsModule } from '@angular/material/tabs';

<mat-tab-group> <mat-tab label="Overview"> <div class="tab-content">Overview content</div> </mat-tab> <mat-tab label="Details"> <div class="tab-content">Details content</div> </mat-tab> <mat-tab label="Settings"> <div class="tab-content">Settings content</div> </mat-tab> </mat-tab-group>

  1. Layout Components

Cards:

import { MatCardModule } from '@angular/material/card';

<mat-card> <mat-card-header> <mat-card-title>Card Title</mat-card-title> <mat-card-subtitle>Card Subtitle</mat-card-subtitle> </mat-card-header>

<img mat-card-image src="image.jpg" alt="Photo">

<mat-card-content> <p>Card content goes here</p> </mat-card-content>

<mat-card-actions> <button mat-button>LIKE</button> <button mat-button>SHARE</button> </mat-card-actions> </mat-card>

Grid List:

import { MatGridListModule } from '@angular/material/grid-list';

<mat-grid-list cols="3" rowHeight="200px"> @for (tile of tiles; track tile.id) { <mat-grid-tile [colspan]="tile.cols" [rowspan]="tile.rows"> <img [src]="tile.image" [alt]="tile.title"> <mat-grid-tile-footer> <h3>{{ tile.title }}</h3> </mat-grid-tile-footer> </mat-grid-tile> } </mat-grid-list>

  1. Buttons & Indicators

Buttons:

import { MatButtonModule } from '@angular/material/button';

<!-- Different button types --> <button mat-button>Basic</button> <button mat-raised-button color="primary">Raised</button> <button mat-flat-button color="accent">Flat</button> <button mat-stroked-button>Stroked</button> <button mat-icon-button><mat-icon>favorite</mat-icon></button> <button mat-fab color="primary"><mat-icon>add</mat-icon></button> <button mat-mini-fab color="accent"><mat-icon>edit</mat-icon></button>

Progress Indicators:

import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressBarModule } from '@angular/material/progress-bar';

<!-- Spinner --> <mat-spinner></mat-spinner> <mat-spinner diameter="50"></mat-spinner>

<!-- Progress bar --> <mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="determinate" [value]="progressValue"></mat-progress-bar>

  1. Popups & Modals

Dialog:

import { MatDialogModule, MatDialog } from '@angular/material/dialog';

// Open dialog openDialog() { const dialogRef = this.dialog.open(MyDialogComponent, { width: '600px', data: { name: 'User Name' } });

dialogRef.afterClosed().subscribe(result => { console.log('Dialog result:', result); }); }

// Dialog component @Component({ template: &#x3C;h2 mat-dialog-title>Dialog Title&#x3C;/h2> &#x3C;mat-dialog-content> &#x3C;p>Dialog content&#x3C;/p> &#x3C;/mat-dialog-content> &#x3C;mat-dialog-actions align="end"> &#x3C;button mat-button mat-dialog-close>Cancel&#x3C;/button> &#x3C;button mat-raised-button color="primary" [mat-dialog-close]="true"> Confirm &#x3C;/button> &#x3C;/mat-dialog-actions> }) export class MyDialogComponent { constructor(@Inject(MAT_DIALOG_DATA) public data: any) {} }

Snackbar:

import { MatSnackBarModule, MatSnackBar } from '@angular/material/snackbar';

showSnackbar() { this.snackBar.open('Message sent successfully!', 'Close', { duration: 3000, horizontalPosition: 'end', verticalPosition: 'top' }); }

Bottom Sheet:

import { MatBottomSheetModule, MatBottomSheet } from '@angular/material/bottom-sheet';

openBottomSheet() { this.bottomSheet.open(BottomSheetComponent); }

  1. Data Tables

Table with Sorting & Pagination:

import { MatTableModule } from '@angular/material/table'; import { MatSortModule, MatSort } from '@angular/material/sort'; import { MatPaginatorModule, MatPaginator } from '@angular/material/paginator';

@Component({ template: ` <table mat-table [dataSource]="dataSource" matSort> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th> <td mat-cell *matCellDef="let element">{{ element.name }}</td> </ng-container>

  &#x3C;ng-container matColumnDef="email">
    &#x3C;th mat-header-cell *matHeaderCellDef mat-sort-header>Email&#x3C;/th>
    &#x3C;td mat-cell *matCellDef="let element">{{ element.email }}&#x3C;/td>
  &#x3C;/ng-container>
  
  &#x3C;tr mat-header-row *matHeaderRowDef="displayedColumns">&#x3C;/tr>
  &#x3C;tr mat-row *matRowDef="let row; columns: displayedColumns;">&#x3C;/tr>
&#x3C;/table>

&#x3C;mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]">
&#x3C;/mat-paginator>

` }) export class TableComponent implements AfterViewInit { displayedColumns = ['name', 'email']; dataSource = new MatTableDataSource(this.data);

@ViewChild(MatSort) sort!: MatSort; @ViewChild(MatPaginator) paginator!: MatPaginator;

ngAfterViewInit() { this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; } }

🎯 Best Practices

  1. Import Only What You Need

// ✅ Good - Import specific modules import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon';

// ❌ Bad - Don't import everything import * as Material from '@angular/material';

  1. Use Appearance Variants

// Material form fields support different appearances <mat-form-field appearance="fill"> <!-- Default --> <mat-form-field appearance="outline"> <!-- Outlined --> <mat-form-field appearance="legacy"> <!-- Deprecated -->

  1. Leverage Color Themes

// Use color attribute for semantic styling <button mat-raised-button color="primary">Primary</button> <button mat-raised-button color="accent">Accent</button> <button mat-raised-button color="warn">Warn</button>

  1. Accessibility

// Always provide labels and ARIA attributes <button mat-icon-button aria-label="Delete item"> <mat-icon>delete</mat-icon> </button>

<mat-form-field> <mat-label>Email</mat-label> <!-- Always include labels --> <input matInput type="email"> </mat-form-field>

  1. Responsive Design

// Use Material breakpoints @use '@angular/material' as mat;

@media (max-width: mat.$small-breakpoint) { .sidenav { mode: 'over'; } }

🔧 Theming

Custom Theme

@use '@angular/material' as mat;

$my-primary: mat.define-palette(mat.$indigo-palette); $my-accent: mat.define-palette(mat.$pink-palette); $my-warn: mat.define-palette(mat.$red-palette);

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

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

🐛 Troubleshooting

Issue Solution

Animations not working Import provideAnimations() or BrowserAnimationsModule

Icons not showing Import Material Icons font in index.html

Styles not applying Import @angular/material/prebuilt-themes in styles.scss

Form field errors Wrap input in <mat-form-field> with <mat-label>

Table not sorting Add MatSort directive and set dataSource.sort

Dialog not opening Inject MatDialog service and import MatDialogModule

📖 References

  • Angular Material Official Docs

  • Component API Reference

  • Material Design Guidelines

  • Angular Material GitHub

📂 Recommended Placement

Project-level skill:

/.github/skills/angular-material/SKILL.md

Copilot will load this when working with Angular Material components.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

material-design-3

No summary provided by upstream source.

Repository SourceNeeds Review
General

architecture-ddd

No summary provided by upstream source.

Repository SourceNeeds Review
General

webapp-testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

angular-material-cdk-animations

No summary provided by upstream source.

Repository SourceNeeds Review