{"schemaVersion":"1.0","type":"TechArticle","types":["Article","TechArticle"],"slug":"introducing-mat-expressive-material-3-expressive-for-angular-material-yyzk8","url":"https://api.zyvop.com/introducing-mat-expressive-material-3-expressive-for-angular-material-yyzk8","title":"Introducing Mat Expressive: Material 3 Expressive for Angular Material","subtitle":"Mat Expressive layers Material 3 Expressive — spring motion, shape morphing, and bold sizing — on top of Angular Material, without forking or replacing it.","tldr":"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...","keywords":["SCSS","angular","Material Design","TypeScript","Angular Material","Material Expressive","News"],"entities":["Dharmen Shah","Frontend developer","SCSS","angular","Material Design","TypeScript","Angular Material","Material Expressive","News","ZyVOP"],"keyTakeaways":["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."],"headings":["What is Mat Expressive?","Installation","A first component: the expressive button","Shape morphing, and why it's a directive and not just CSS","Toggle state: a deliberate design choice","Cutting the CSS payload","What's included so far","Try it"],"outboundLinks":["https://material.angular.dev/guide/theming#component-tokens","https://expressive.angular-material.dev/","https://github.com/Angular-Material-Dev/mat-exp","https://x.com/ngMaterialDev"],"contentText":"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: &lt;button matButton=\"elevated\" class=\"mat-exp-button\" data-size=\"xs\" data-shape=\"square\"&gt; Elevated &lt;/button&gt; &lt;button matButton=\"tonal\" class=\"mat-exp-button\" data-size=\"s\"&gt;Tonal&lt;/button&gt; 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: ` &lt;button matButton=\"elevated\" size=\"xs\" shape=\"square\" matExpButton&gt;Elevated&lt;/button&gt; &lt;button matButton=\"tonal\" size=\"s\" matExpButton&gt;Tonal&lt;/button&gt; `, }) 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 &lt;mat-exp-button-group&gt;. 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: ` &lt;button matButton=\"tonal\" matExpButton [(toggle)]=\"favorited\" (click)=\"favorited.set(favorited() === 'selected' ? 'unselected' : 'selected')\" &gt; Favorite &lt;/button&gt; `, }) export class App { protected readonly favorited = model&lt;'selected' | 'unselected'&gt;('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 &amp; 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.","contentHash":"sha256:50534809062be4448a5c2686ad889592fd45031525a9b6855df55262449f4bb2","authorName":"Dharmen Shah","authorUrl":"https://api.zyvop.com/author/dharmen","authorSameAs":["https://github.com/shhdharmen","https://x.com/shhdharmen","https://www.linkedin.com/in/shhdharmen?utm_source=share_via&utm_content=profile&utm_medium=member_android"],"category":"News","tags":["SCSS","angular","Material Design","TypeScript","Angular Material","Material Expressive"],"audience":"Software engineers and developers building applications with News","tone":"In-depth technical and architectural analysis","readingTimeMinutes":4,"wordCount":819,"faqs":null,"primaryTopic":"News","publishedAt":"2026-07-31T17:46:36.657Z","updatedAt":"2026-09-01T14:40:00.180Z","canonicalUrl":"https://expressive.angular-material.dev/blogs/announcement"}