ZYVOPMulti-Platform Sync
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZYVOPMulti-Platform Sync

The Developer Publishing Hub. Write once, publish everywhere, and make your work citation-ready with built-in SEO, AEO, and GEO discovery support. Zero reader paywalls.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • Changelog
  • Compare Platforms
  • Hashnode vs ZyVOP
  • DEV vs ZyVOP
  • Developer API & CLI
  • Author Handbook
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Developer Publishing Hub.

Zero paywalls · Full content ownership
All systems operational
HomeNewsIntroducing Mat Expressive: Material 3 Expressive for Angular Material
News

Introducing Mat Expressive: Material 3 Expressive for Angular Material

Mat Expressive layers Material 3 Expressive — spring motion, shape morphing, and bold sizing — on top of Angular Material, without forking or replacing it.

Dharmen Shah
Dharmen Shah
Frontend developer
July 31, 2026Updated September 1, 2026
4 min read
Introducing Mat Expressive: Material 3 Expressive for Angular Material
#SCSS#angular#Material Design#TypeScript#Angular Material#Material Expressive
👍1

What is Mat Expressive?

Mat Expressive is a library of styles, directives, and a few new components that sit on top of Angular Material. It's not a fork and not a replacement — you keep using MatButton, MatFab, and the rest of Angular Material as-is. Mat Expressive layers M3 Expressive behavior onto them.

Concretely, it gives you three things:

  • Styles — SCSS mixins that restyle existing Angular Material components using Material's own component token overrides and CSS variables, so they match M3 Expressive.

  • Directives — for the cases styling alone can't reach (things like shape morphing on press, which need actual behavior, not just CSS).

  • New components — for patterns M3 Expressive defines that Angular Material doesn't have a component for at all (loading indicators, FAB menus, split buttons).

Under the hood, motion is powered by GSAP spring physics, every animation respects prefers-reduced-motion, and the library is SSR-safe.

Installation

ng add @ngm-dev/mat-exp

The schematic wires up the package for you. From there, add the styles you need globally:

// styles.scss
@use '@ngm-dev/mat-exp' as mat-exp;

html {
  @include mat-exp.mat-exp-button-styles();
}

A first component: the expressive button

The clearest way to see what Mat Expressive does is the button. Angular Material already has matButton — Mat Expressive adds size, shape, and toggle variations on top of it, plus the shape-morph-on-press behavior from the M3 Expressive spec.

You can opt in two ways.

Option 1 — CSS class + data attributes, no extra imports beyond styles:

<button matButton="elevated" class="mat-exp-button" data-size="xs" data-shape="square">
  Elevated
</button>
<button matButton="tonal" class="mat-exp-button" data-size="s">Tonal</button>

Option 2 — the matExpButton directive, if you want type safety and two-way bindable inputs:

import { MatButton } from '@angular/material/button';
import { MatExpButton } from '@ngm-dev/mat-exp';

@Component({
  selector: 'app-root',
  imports: [MatButton, MatExpButton],
  template: `
    <button matButton="elevated" size="xs" shape="square" matExpButton>Elevated</button>
    <button matButton="tonal" size="s" matExpButton>Tonal</button>
  `,
})
export class App {}

Both approaches give you the same variations:

  • Size: xs, s, m, l, xl

  • Shape: round, square

  • Toggle: selected, unselected

  • State: pressed (driven by the :active pseudo-selector)

Shape morphing, and why it's a directive and not just CSS

One of the defining traits of M3 Expressive buttons is that they morph shape when pressed — round buttons square off slightly, and both round and square buttons converge on the same pressed shape. Toggle buttons go further: the resting shape itself changes between selected and unselected states.

This is exactly the kind of thing that can't be pure CSS — it needs to read component state and react to it — which is why matExpButton exists as a directive rather than just a stylesheet.

Accessibility is handled automatically here too: the shape-morph transition stops entirely under prefers-reduced-motion: reduce, because matExpButton piggybacks on Angular Material's own matButton host, which already detects the setting.

Toggle state: a deliberate design choice

If you've used a toggle button before, you might expect toggle to flip on click automatically. In Mat Expressive, it doesn't — unless the button lives inside a <mat-exp-button-group>.

For a standalone toggle button, the library leaves the click-to-state transition up to you:

import { signal } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatExpButton } from '@ngm-dev/mat-exp';

@Component({
  selector: 'app-root',
  imports: [MatButton, MatExpButton],
  template: `
    <button
      matButton="tonal"
      matExpButton
      [(toggle)]="favorited"
      (click)="favorited.set(favorited() === 'selected' ? 'unselected' : 'selected')"
    >
      Favorite
    </button>
  `,
})
export class App {
  protected readonly favorited = model<'selected' | 'unselected'>('unselected');
}

This is intentional rather than an oversight: a lone button only has one consumer for its click event, so guessing what that click should mean would be presumptuous. Inside a MatExpButtonGroup, the group already owns selection state for its buttons — adding your own click handler there would fight it.

Cutting the CSS payload

By default, the style mixins emit CSS for every size × shape × state × toggle combination. If your app only ever uses two or three sizes, you don't need to ship the rest:

@use '@ngm-dev/mat-exp' as mat-exp;

html {
  @include mat-exp.mat-exp-button-styles(
    (
      sizes: ('s', 'm'),
    )
  );
}

There's also a skip-html-element-styles option if you don't want Mat Expressive touching the underlying Angular Material DOM elements at all — useful if you're worried about coupling to Angular Material's internal classes, at the cost of losing icon-size adjustments and shape morphing.

What's included so far

At launch, Mat Expressive covers:

  • Buttons — Button, Icon Button, Button Group, Split Button, FAB Menu

  • Loading & Progress — an M3 Expressive loading indicator with GSAP spring motion

More components are planned, following the same pattern: style what Angular Material already has, build what it doesn't.

Try it

ng add @ngm-dev/mat-exp
  • 📖 Docs: expressive.angular-material.dev

  • 💻 GitHub: github.com/Angular-Material-Dev/mat-exp

  • 🐦 Follow along: @ngMaterialDev

It's MIT licensed and free. If you're building on Angular Material and want the M3 Expressive look — motion, shape morphing, and all — without hand-rolling it yourself, give it a try. Issues and feature requests are welcome on GitHub.

Comments (0)

Login to post a comment.

Dharmen Shah
Dharmen Shah

Frontend developer

Passionate developer sharing knowledge about modern web technologies and best practices.

Subscribe to Dharmen Shah's Newsletter

Direct email dispatches when new stories are published. Zero algorithms.

Trending on ZyVOP

The Harness is the Moat: Building a Deterministic Agent Runtime with Context Pruning

Learn how a deterministic harness prunes context, uses a ledger and transactional tool calls to keep LLM agents reliable over many turns.

Lê Đức Minh
Lê Đức Minh·
6 minSep 16

Building a Synthetic Data Generator

Building a synthetic data generator based on Red Hat's "sdg hub" Introduction For a...

Alain Airom (Ayrom)
Alain Airom (Ayrom)·
10 minSep 16

The Reference Image Looks Right—So Why Does My AI Video Ignore the Prompt?

The mug looks exactly right. It has the blue rim from your reference photo, the same curved handle, and the same morning light on the kitchen counter. But you...

john smith
john smith·
3 minSep 16

Introducing Gemini 3.8 Live and 3.8 Live Extended Thinking

Google launched Gemini 3.8 Live and 3.8 Live Extended Thinking on September 15, 2026, its most advanced voice AI yet. The models reason and speak simultaneously, ground responses in live video, switch between 97 languages, and top several speech benchmarks.

Arpan Singh
Arpan Singh·
3 minSep 16

Gemini 3.8 Live Extended Thinking vs GPT-Live-1 vs Grok Voice Think Fast 2.0: A Developer's Buying Guide

Google, OpenAI, and xAI each released a flagship voice-agent model between late July and mid-September 2026. The headline benchmarks look close, but the three models use very different architectures, and that difference changes the real cost of running one.

Anshu Pathak
Anshu Pathak·
10 minSep 16