Material Design 3
This skill guides implementation of Google's Material Design 3 (MD3) — a personal, adaptive, expressive design system. MD3 uses dynamic color, tonal surfaces, rounded shapes, and spring-based motion to create UIs that feel alive and personal.
Philosophy
MD3 is built on three principles:
- Personal: Dynamic color adapts UI to the user's wallpaper or content. Theming is individual, not one-size-fits-all.
- Adaptive: Layouts transform across 5 window size classes. Components resize, reposition, and change form factor responsively.
- Expressive: Shape morphing, spring physics, and emphasized typography create moments of delight without sacrificing usability.
Current Updates: Google I/O 2026
Material's Google I/O 2026 update reinforces a Compose-first Android path and expands expressive/adaptive guidance:
- Material Android is Compose-first: For new Android work, prefer Jetpack Compose Material3 for the latest components, expressive APIs, adaptive scaffolds, and Styles API integration. Android Views may remain necessary in existing apps, but they should not be treated as the default path for new Material 3 implementations.
- Expressive layout system: Use an expressive layout scaffold to adapt screens across mobile, desktop, foldables, watches, XR, and other spatial form factors. Start from adaptive scaffolds/window size classes instead of fixed phone-first layouts.
- 8dp spacing system: Apply spacing tokens for margins, padding, and gaps so layouts and components can adapt programmatically to device type and density.
- New/updated expressive components: Lists, menus, search, and search app bars have refreshed expressive guidance, with Jetpack Compose as the primary implementation target.
- Watches and XR: Watches emphasize physics-based motion, arc text, and edge-hugging containers. XR emphasizes spatial panels and depth-based elevation.
Key differences from MD2:
- Tonal surfaces replace elevation shadows as the primary depth cue
- Dynamic color generates full schemes from a single seed color
- Fully rounded corners by default (not slightly rounded)
- Spring-based motion physics replace fixed easing curves for components
- 3 levels of user-controlled contrast (standard/medium/high)
Relationship with frontend-design skill:
When both skills are active, MD3 provides the design system (tokens, components, layout rules) and frontend-design provides creative direction within those constraints. MD3 rules take precedence for component structure and token usage. Note: Roboto/Roboto Flex IS the correct default typeface in MD3 — the frontend-design guidance to avoid Roboto does not apply when implementing MD3.
Decision Tree
What are you building?
Full app scaffold → See "Common Patterns: App Shell" + references/layout-and-responsive.md
Single component → See "Component Quick Reference" table → references/component-catalog.md
Custom theme → See references/theming-and-dynamic-color.md
Form / input layout → See references/component-catalog.md § Input Components
Navigation structure → See references/navigation-patterns.md
Data display → See references/component-catalog.md § Data Display
What platform?
Jetpack Compose → Primary: androidx.compose.material3, MaterialTheme, references/*
Flutter → useMaterial3: true in ThemeData, ColorScheme.fromSeed()
Web (vanilla JS) → @material/web (limited; maintenance mode) + CSS custom properties
Web (React/Vue/Svelte) → CSS custom properties + wrapper components (no official React lib)
Web (CSS-only) → MD3 token values as CSS custom properties (no <md-*> elements)
Design Token System
All MD3 tokens use the md.sys namespace. Jetpack Compose maps roles to MaterialTheme.colorScheme, MaterialTheme.typography, and MaterialTheme.shapes (same semantic roles as the spec). On the web, these map to CSS custom properties (--md-sys-*):
Color Tokens (--md-sys-color-*)
| Token |
Purpose |
primary |
High-emphasis fills, text, icons against surface |
on-primary |
Text/icons on primary |
primary-container |
Standout fill for key components (FAB, etc.) |
on-primary-container |
Text/icons on primary-container |
secondary / on-secondary |
Less prominent accents |
secondary-container / on-secondary-container |
Recessive components (tonal buttons) |
tertiary / on-tertiary |
Contrasting accents |
tertiary-container / on-tertiary-container |
Complementary containers |
error / on-error |
Error states (static — doesn't change with dynamic color) |
error-container / on-error-container |
Error container fills |
surface |
Default background |
on-surface |
Text/icons on any surface |
on-surface-variant |
Lower-emphasis text/icons on surface |
surface-container-lowest |
Lowest-emphasis container |
surface-container-low |
Low-emphasis container |
surface-container |
Default container (nav areas) |
surface-container-high |
High-emphasis container |
surface-container-highest |
Highest-emphasis container |
surface-dim / surface-bright |
Maintain relative brightness across light/dark |
inverse-surface / inverse-on-surface / inverse-primary |
Contrasting elements (snackbars) |
outline |
Important boundaries (text field borders) |
outline-variant |
Decorative elements (dividers) |
Full details: references/color-system.md
Typography Tokens (--md-sys-typescale-*)
| Scale |
Sizes |
Use |
| Display |
L / M / S |
Hero text, large numbers |
| Headline |
L / M / S |
Section headers |
| Title |
L / M / S |
Smaller headers, card titles |
| Body |
L / M / S |
Paragraph text, descriptions |
| Label |
L / M / S |
Buttons, chips, captions |
Each style has tokens for: -font, -weight, -size, -line-height, -tracking
Plus 15 emphasized variants (higher weight) via --md-sys-typescale-emphasized-*
Full details: references/typography-and-shape.md
Shape Tokens (--md-sys-shape-corner-*)
| Token |
Value |
Example components |
none |
0dp |
— |
extra-small |
4dp |
Chips, snackbars |
small |
8dp |
Text fields, menus |
medium |
12dp |
Cards |
large |
16dp |
FABs, navigation drawer |
large-increased |
20dp |
(Expressive) |
extra-large |
28dp |
Dialogs, bottom sheets |
extra-large-increased |
32dp |
(Expressive) |
extra-extra-large |
48dp |
(Expressive) |
full |
9999px |
Buttons, chips, badges |
Elevation Levels
| Level |
DP |
Tonal offset |
Use |
| 0 |
0dp |
None |
Flat surfaces, most components at rest |
| 1 |
1dp |
+5% primary |
Elevated cards, modal sheets |
| 2 |
3dp |
+8% primary |
Menus, nav bar, scrolled app bar |
| 3 |
6dp |
+11% primary |
FAB, dialogs, search, date/time pickers |
| 4 |
8dp |
+12% primary |
(hover/focus increase only) |
| 5 |
12dp |
+14% primary |
(hover/focus increase only) |
Elevation in MD3 is communicated through tonal surface color, not shadows. Shadows are only used when needed for additional protection against busy backgrounds.
Motion
MD3 Expressive (May 2025) introduced spring-based motion physics for components. The legacy easing/duration system is still used for transitions (enter/exit/shared-axis):
| Easing |
Duration |
Transition type |
| Emphasized |
500ms |
Begin and end on screen |
| Emphasized decelerate |
400ms |
Enter the screen |
| Emphasized accelerate |
200ms |
Exit the screen |
| Standard |
300ms |
Begin and end on screen (utility) |
| Standard decelerate |
250ms |
Enter screen (utility) |
| Standard accelerate |
200ms |
Exit screen (utility) |
CSS easing values:
- Emphasized:
cubic-bezier(0.2, 0, 0, 1)
- Emphasized decelerate:
cubic-bezier(0.05, 0.7, 0.1, 1)
- Emphasized accelerate:
cubic-bezier(0.3, 0, 0.8, 0.15)
- Standard:
cubic-bezier(0.2, 0, 0, 1)
- Standard decelerate:
cubic-bezier(0, 0, 0, 1)
- Standard accelerate:
cubic-bezier(0.3, 0, 1, 1)
Component Quick Reference
| Component |
Web Element |
Key Variants |
Category |
| Button |
md-filled-button, md-outlined-button, md-text-button, md-elevated-button, md-filled-tonal-button |
Filled, Outlined, Text, Elevated, Tonal; 5 sizes (XS–XL); toggle |
Actions |
| Button group |
md-button-group |
Standard, connected |
Actions |
| Extended FAB |
md-extended-fab |
Surface, Primary, Secondary, Tertiary |
Actions |
| FAB |
md-fab |
Small, Medium, Large |
Actions |
| FAB menu |
— |
— |
Actions |
| Icon button |
md-icon-button, md-filled-icon-button, md-filled-tonal-icon-button, md-outlined-icon-button |
Standard, Filled, Filled Tonal, Outlined |
Actions |
| Segmented button |
— |
Single-select, Multi-select |
Actions |
| Split button |
— |
— |
Actions |
| Badge |
— |
Small (dot), Large (count) |
Communication |
| Loading indicator |
— |
Linear, Circular |
Communication |
| Progress indicator |
md-linear-progress, md-circular-progress |
Linear, Circular; determinate/indeterminate |
Communication |
| Snackbar |
— |
Single-line, Two-line, Action |
Communication |
| Tooltip |
— |
Plain, Rich |
Communication |
| Card |
— |
Filled, Outlined, Elevated |
Containment |
| Carousel |
— |
Multi-browse, Uncontained, Hero |
Containment |
| Dialog |
md-dialog |
Basic, Full-screen |
Containment |
| Bottom sheet |
— |
Standard, Modal |
Sheets |
| Side sheet |
— |
Standard, Modal |
Sheets |
| Divider |
md-divider |
Full-width, Inset |
Containment |
| Checkbox |
md-checkbox |
— |
Input |
| Chips |
md-chip-set, md-assist-chip, md-filter-chip, md-input-chip, md-suggestion-chip |
Assist, Filter, Input, Suggestion |
Input |
| Date picker |
— |
Docked, Modal, Range |
Input |
| Menu |
md-menu, md-menu-item |
— |
Input |
| Radio button |
md-radio |
— |
Input |
| Slider |
md-slider |
Continuous, Discrete, Range |
Input |
| Switch |
md-switch |
With/without icon |
Input |
| Text field |
md-filled-text-field, md-outlined-text-field |
Filled, Outlined |
Input |
| Time picker |
— |
Docked, Modal |
Input |
| App bar (top) |
— |
Center-aligned, Small, Medium, Large |
Navigation |
| Navigation bar |
md-navigation-bar |
— |
Navigation |
| Navigation drawer |
md-navigation-drawer |
Standard, Modal |
Navigation |
| Navigation rail |
— |
— |
Navigation |
| Search |
— |
Search bar, Search view |
Navigation |
| Tabs |
md-tabs, md-primary-tab, md-secondary-tab |
Primary, Secondary |
Navigation |
| Toolbar |
— |
— |
Navigation |
| List |
md-list, md-list-item |
One-line, Two-line, Three-line |
Data Display |
Note: Components marked with — for web element don't have @material/web implementations yet. Use CSS custom properties with standard HTML for these. Compose mappings and examples live in references/component-catalog.md.
Full component details with code examples: references/component-catalog.md
Jetpack Compose (primary)
Use androidx.compose.material3 with MaterialTheme and Material 3 composables (Scaffold, Button, NavigationBar, top app bars, etc.).
- Theming:
MaterialTheme(colorScheme = …, typography = …, shapes = …). Prefer dynamicLightColorScheme / dynamicDarkColorScheme on Android 12+ (API 31+) when dynamic color is desired; otherwise lightColorScheme / darkColorScheme or generated theme code from Material Theme Builder.
- Adaptive UI: Window size classes, list-detail and supporting-pane layouts, foldables — see
references/layout-and-responsive.md and references/navigation-patterns.md.
- Edge-to-edge & insets: Lay out content with
WindowInsets / scaffold padding so bars and IME behave correctly — see references/layout-and-responsive.md.
- Experimental APIs: Some Material 3 APIs require
@OptIn(ExperimentalMaterial3Api::class) or expressive opt-ins; match your BOM and compiler.
MaterialTheme(
colorScheme = colorScheme, // from dynamicLightColorScheme / lightColorScheme / etc.
typography = Typography(),
shapes = Shapes(),
) {
// M3 content — prefer references for Scaffold, navigation, text fields
}
Web (limited): @material/web
Important: Per Material Design 3 for Web, Material Web Components are in maintenance mode and M3 Expressive is not implemented on Web. Use @material/web for token-backed web UIs when appropriate, but do not treat it as equivalent to Compose for current Expressive features.
Setup
npm install @material/web
Import Components Individually
Always import only the components you use — importing the entire package bloats the bundle:
// Good — individual imports
import '@material/web/button/filled-button.js';
import '@material/web/button/outlined-button.js';
import '@material/web/textfield/outlined-text-field.js';
import '@material/web/icon/icon.js';
// Bad — never do this
import '@material/web'; // imports everything
Basic Usage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@400;500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined" rel="stylesheet">
</head>
<body>
<md-filled-button>Get started</md-filled-button>
<md-outlined-text-field label="Email" type="email"></md-outlined-text-field>
<script type="module">
import '@material/web/button/filled-button.js';
import '@material/web/textfield/outlined-text-field.js';
</script>
</body>
</html>
Theming with CSS Custom Properties
Apply a custom theme by setting CSS custom properties on :root or any ancestor:
:root {
/* Color scheme (generate with @material/material-color-utilities) */
--md-sys-color-primary: #6750A4;
--md-sys-color-on-primary: #FFFFFF;
--md-sys-color-primary-container: #EADDFF;
--md-sys-color-on-primary-container: #21005D;
--md-sys-color-secondary: #625B71;
--md-sys-color-on-secondary: #FFFFFF;
--md-sys-color-secondary-container: #E8DEF8;
--md-sys-color-on-secondary-container: #1D192B;
--md-sys-color-surface: #FEF7FF;
--md-sys-color-on-surface: #1D1B20;
--md-sys-color-surface-container: #F3EDF7;
--md-sys-color-outline: #79747E;
--md-sys-color-outline-variant: #CAC4D0;
/* Typography */
--md-sys-typescale-body-large-font: 'Roboto Flex', sans-serif;
--md-sys-typescale-body-large-size: 1rem;
--md-sys-typescale-body-large-weight: 400;
--md-sys-typescale-body-large-line-height: 1.5rem;
/* Shape */
--md-sys-shape-corner-full: 9999px;
--md-sys-shape-corner-medium: 12px;
}
Component-Level Overrides
Override individual component tokens for specific customization:
md-filled-button {
--md-filled-button-container-color: var(--md-sys-color-primary);
--md-filled-button-label-text-color: var(--md-sys-color-on-primary);
--md-filled-button-container-shape: var(--md-sys-shape-corner-full);
--md-filled-button-container-height: 40px;
}
md-outlined-text-field {
--md-outlined-text-field-container-shape: var(--md-sys-shape-corner-small);
--md-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);
}
Dark Theme
Apply dark theme by overriding color tokens on a class or media query:
@media (prefers-color-scheme: dark) {
:root {
--md-sys-color-primary: #D0BCFF;
--md-sys-color-on-primary: #381E72;
--md-sys-color-primary-container: #4F378B;
--md-sys-color-on-primary-container: #EADDFF;
--md-sys-color-surface: #141218;
--md-sys-color-on-surface: #E6E0E9;
--md-sys-color-surface-container: #211F26;
--md-sys-color-outline: #938F99;
--md-sys-color-outline-variant: #49454F;
}
}
Full theming guide: references/theming-and-dynamic-color.md
Common Patterns
App Shell
Standard MD3 app with responsive navigation + top app bar + content area:
<div class="md3-app">
<nav class="md3-nav-rail" aria-label="Main navigation">
<!-- Navigation rail for medium+ screens -->
<md-fab size="small" aria-label="Compose">
<md-icon slot="icon">edit</md-icon>
</md-fab>
<md-navigation-bar>
<md-navigation-tab label="Home">
<md-icon slot="active-icon">home</md-icon>
<md-icon slot="inactive-icon">home</md-icon>
</md-navigation-tab>
<md-navigation-tab label="Search">
<md-icon slot="active-icon">search</md-icon>
<md-icon slot="inactive-icon">search</md-icon>
</md-navigation-tab>
</md-navigation-bar>
</nav>
<main class="md3-content">
<header class="md3-top-app-bar">
<h1 class="md3-top-app-bar__title" style="font: var(--md-sys-typescale-title-large)">
Page Title
</h1>
</header>
<div class="md3-body">
<!-- Content here -->
</div>
</main>
</div>
.md3-app {
display: flex;
min-height: 100vh;
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
}
.md3-nav-rail {
width: 80px;
background: var(--md-sys-color-surface);
border-right: 1px solid var(--md-sys-color-outline-variant);
display: flex;
flex-direction: column;
align-items: center;
padding-top: 12px;
gap: 12px;
}
.md3-content {
flex: 1;
display: flex;
flex-direction: column;
}
.md3-top-app-bar {
height: 64px;
padding: 0 16px;
display: flex;
align-items: center;
background: var(--md-sys-color-surface);
}
.md3-body {
padding: 24px;
flex: 1;
}
/* Responsive: switch to bottom nav on compact */
@media (max-width: 599px) {
.md3-app { flex-direction: column; }
.md3-nav-rail {
order: 1;
width: 100%;
flex-direction: row;
justify-content: center;
border-right: none;
border-top: 1px solid var(--md-sys-color-outline-variant);
padding: 0;
}
}
Card Grid
<div class="md3-card-grid">
<div class="md3-card md3-card--outlined">
<img src="image.jpg" alt="Description" class="md3-card__media">
<div class="md3-card__content">
<h3 style="font: var(--md-sys-typescale-title-medium)">Card Title</h3>
<p style="font: var(--md-sys-typescale-body-medium); color: var(--md-sys-color-on-surface-variant)">
Supporting text for this card.
</p>
</div>
<div class="md3-card__actions">
<md-text-button>Learn more</md-text-button>
<md-filled-tonal-button>Action</md-filled-tonal-button>
</div>
</div>
</div>
.md3-card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 16px;
}
.md3-card--outlined {
border: 1px solid var(--md-sys-color-outline-variant);
border-radius: var(--md-sys-shape-corner-medium, 12px);
background: var(--md-sys-color-surface);
overflow: hidden;
}
.md3-card__content { padding: 16px; }
.md3-card__actions { padding: 8px 16px 16px; display: flex; gap: 8px; justify-content: flex-end; }
.md3-card__media { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
Form Layout
<form class="md3-form">
<md-outlined-text-field label="Full name" required></md-outlined-text-field>
<md-outlined-text-field label="Email" type="email" required></md-outlined-text-field>
<md-outlined-text-field label="Message" type="textarea" rows="4"></md-outlined-text-field>
<div class="md3-form__actions">
<md-text-button type="reset">Cancel</md-text-button>
<md-filled-button type="submit">Submit</md-filled-button>
</div>
</form>
.md3-form {
display: flex;
flex-direction: column;
gap: 16px;
max-width: 560px;
}
.md3-form__actions {
display: flex;
gap: 8px;
justify-content: flex-end;
margin-top: 8px;
}
More patterns: references/navigation-patterns.md, references/layout-and-responsive.md
Anti-Patterns
Never do these when implementing MD3:
- Mix MD2 and MD3 libraries: Don't use
@material/mdc-* (MD2) alongside @material/web (MD3). They have incompatible APIs and styling.
- Hardcode colors: Always use
var(--md-sys-color-*) tokens, never raw hex/rgb values. Hardcoded colors break dynamic theming, dark mode, and contrast adjustment.
- Ignore tonal pairing: Only combine colors in their intended pairs (e.g.,
primary + on-primary, surface-container + on-surface). Arbitrary pairings break contrast in dynamic color and high contrast modes.
- Use
outline for dividers: Use outline-variant for dividers. outline is for important boundaries like text field borders.
- Import all of @material/web: Always import individual component modules. Barrel imports include every component and destroy bundle size.
- Use
border-radius directly: Use shape tokens (var(--md-sys-shape-corner-medium)) so shapes stay consistent with theming.
- Use shadows for elevation by default: MD3 communicates elevation through tonal surface color, not shadows. Only add shadows when elements need extra separation from busy backgrounds.
- Apply frontend-design "avoid Roboto" rule: On Android, Roboto is the default Material typeface; web often uses Roboto or Roboto Flex with MD3 tokens. Replace only when intentionally customizing the type scale.
- Assume SSR compatibility:
@material/web uses Web Components (custom elements) which require JavaScript to render. They won't produce meaningful HTML in SSR without additional hydration strategies.
- Ignore foldables and large screens: MD3 is designed for all screen sizes. Don't ship phone-only layouts — use canonical layouts, multi-pane at 600dp+, and test on foldable/tablet emulators. Place no interactive content across the fold/hinge.
- Stretch content to fill wide screens: On Large (1200dp+) and Extra-large (1600dp+) windows, constrain content to a max width (840–1040dp). Endless-width text lines are unreadable.
Platform Notes
Flutter
MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
);
Jetpack Compose
See Jetpack Compose (primary) above. Use LocalContext.current with dynamicLightColorScheme / dynamicDarkColorScheme only when Build.VERSION.SDK_INT >= Build.VERSION_CODES.S and dynamic color is enabled; otherwise supply static light/dark schemes.
Component Name Mapping
| Concept |
Web |
Flutter |
Compose |
| Filled button |
md-filled-button |
FilledButton |
Button |
| Outlined text field |
md-outlined-text-field |
OutlinedTextField |
OutlinedTextField |
| FAB |
md-fab |
FloatingActionButton |
FloatingActionButton |
| Navigation bar |
md-navigation-bar |
NavigationBar |
NavigationBar |
| Switch |
md-switch |
Switch |
Switch |
M3 Expressive (May 2025)
The Expressive update adds visual richness while maintaining usability. Availability differs by platform — do not assume one stack implements everything.
| Capability |
Jetpack Compose |
Flutter |
Web (@material/web) |
| Expressive layout scaffold / adaptive layout |
Compose-first via Material3 adaptive APIs and window size classes |
Use Flutter adaptive/layout primitives |
CSS/container queries/manual layout; no Material Web parity |
| 8dp spacing system |
Use design tokens / Dp spacing constants; keep margins, padding, and gaps adaptive |
Use theme spacing constants |
CSS custom properties / design tokens |
| Expressive lists, menus, search, search app bar |
Primary target per current Material guidance; check BOM and opt-ins |
Check current Flutter Material docs |
Spec-aligned custom implementation; @material/web is maintenance-only |
| Spring / motion physics |
Supported in Material 3 (see MotionScheme, expressive APIs per BOM) |
Varies by Flutter Material version |
Not in Material Web; use easing/duration or custom motion |
| Emphasized typography |
Via theme / type scale |
Via theme |
Token/CSS only; no full Expressive component set |
| Shape morphing |
Compose-first in Google’s expressive rollout |
Check current Flutter docs |
Not in @material/web |
| New button sizes (XS–XL), toggle |
Follow Compose Material3 components |
Follow Flutter MD3 |
Height/CSS approximations only |
| Extra corner tokens (e.g. large-increased) |
MaterialTheme.shapes / tokens |
Theme shapes |
CSS --md-sys-shape-* |
| 3 contrast levels |
Scheme builders / system |
Plugins / manual |
SchemeContent contrast parameter in JS utilities |
| Watches / XR form factors |
Use Compose/Wear/XR-specific guidance where available |
Platform-specific |
Web/spatial UI custom implementation |
Web: Material Web is maintenance-only; M3 Expressive is not on Web. Use CSS easing/duration tokens as fallback for motion, not spring parity.
Legacy easing/duration remains valid for transitions (enter/exit/shared-axis) where the spec still references them; see the Motion table below.
MD3 Compliance Audit
When invoked with audit as the argument (e.g., /material-3 audit), or when asked to audit/review MD3 compliance, analyze the target app or page and produce a compliance report.
Audit Procedure
- Identify the target: The user provides a URL (use browser tools to inspect), file paths (read source), or a running app.
- Inspect the following categories and score each 0–10:
| Category |
What to check |
| Color tokens |
Web: --md-sys-color-* / generated CSS. Compose: MaterialTheme.colorScheme roles (no arbitrary Color(...) for surfaces without reason). Proper tonal pairing (onX on X). Dark theme. Flutter: ColorScheme roles. |
| Typography |
MD3 type scale: Compose MaterialTheme.typography; web typescale tokens; correct roles (Display, Headline, Title, Body, Label). |
| Shape |
Compose MaterialTheme.shapes / component Shape; web var(--md-sys-shape-*). Buttons: full; cards: medium; avoid magic numbers. |
| Elevation |
Tonal elevation (Surface tonal/shadow as appropriate). Web: hover/focus where relevant. |
| Components |
Compose: Material3 composables (Button, Scaffold, etc.). Web: @material/web or spec-aligned HTML/CSS. Correct variants. |
| Layout |
Canonical layouts; Compose window size class / adaptive APIs; readable max width on large widths; foldable hinge avoidance. |
| Navigation |
Bar / rail / drawer / drawers+Compose NavHost patterns per size class; predictive back where applicable. |
| Motion |
Compose MotionScheme / expressive APIs when used; transitions may still use easing/duration. Web: CSS motion tokens fallback. |
| Accessibility |
MD3 roles help, but verify contrast: UI components often need 3:1 for large text/borders and 4.5:1 for normal text (WCAG 2.x). TalkBack/semantics (Compose), focus order, touch targets (~48dp). Web: ARIA, keyboard. |
| Theming |
Compose: MaterialTheme + light/dark/dynamic as designed. Web: CSS custom properties on :root or subtree. Flutter: ThemeData + ColorScheme. |
- Generate the report:
# MD3 Compliance Audit Report
Target: [URL or file path]
Date: [date]
Overall Score: [X/100]
## Scores by Category
| Category | Score | Status |
|----------------|-------|--------|
| Color tokens | X/10 | [pass/warn/fail] |
| Typography | X/10 | [pass/warn/fail] |
| Shape | X/10 | [pass/warn/fail] |
| Elevation | X/10 | [pass/warn/fail] |
| Components | X/10 | [pass/warn/fail] |
| Layout | X/10 | [pass/warn/fail] |
| Navigation | X/10 | [pass/warn/fail] |
| Motion | X/10 | [pass/warn/fail] |
| Accessibility | X/10 | [pass/warn/fail] |
| Theming | X/10 | [pass/warn/fail] |
## Critical Issues
[List items scoring 0-3 with specific file:line references and fixes]
## Warnings
[List items scoring 4-6 with recommendations]
## Passing
[List items scoring 7-10 with notes on what's done well]
## Recommended Fixes (Priority Order)
1. [Most impactful fix first]
2. ...
Audit Methods
For a live URL (browser or devtools):
- Inspect computed styles and CSS variables (
--md-sys-*)
- Resize viewport or use responsive mode for breakpoints
- Capture screenshots at key widths if helpful
For source code (file paths provided):
- Compose/Kotlin:
.kt files — MaterialTheme, composables, Color(0x…) abuse, hard-coded Dp, missing Modifier.semantics where needed
- Flutter:
.dart — ThemeData, ColorScheme
- Web: HTML/JSX/Vue/Svelte; CSS/SCSS for tokens
- Check web imports for
@material/web vs @material/mdc-* (MD2)
Quick checks (adapt paths to your stack):
# Web: hardcoded colors
grep -rn '#[0-9a-fA-F]\{3,8\}' --include='*.css' --include='*.scss'
# Compose: raw Color(...) audits (sample — tune for your codebase)
grep -rn 'Color(0x' --include='*.kt'
# MD2 on web
grep -rn '@material/mdc-' --include='*.js' --include='*.ts'
Browser automation (if your environment exposes MCP browser tools): navigate, snapshot DOM/CSS variables, resize for breakpoints — optional, not required.
Scoring Guide
- 9-10: Fully MD3 compliant, uses correct tokens and patterns
- 7-8: Mostly compliant, minor issues (e.g., a few hardcoded values)
- 4-6: Partially compliant, some MD3 patterns but significant gaps
- 1-3: Major violations, mostly non-MD3 or MD2 patterns
- 0: Not applicable or completely absent
Status thresholds: pass (7+), warn (4-6), fail (0-3)
Reference Documents
references/color-system.md — Color roles, tonal palettes, dynamic color, Compose + CSS mapping
references/typography-and-shape.md — Type scale, shape corners, elevation, motion, Expressive notes
references/component-catalog.md — Components: Compose + @material/web where applicable
references/navigation-patterns.md — Navigation selection, Compose-first adaptive patterns
references/layout-and-responsive.md — Breakpoints, canonical layouts, insets, foldables
references/theming-and-dynamic-color.md — Theming: Compose first, then Flutter and web
1---2name: material-33description: Implement Google's Material Design 3 (Material You) UI system. Primary: Jetpack Compose Material3 (MaterialTheme, components, adaptive layout). Also Flutter and limited web (@material/web, maintenance mode). Covers tokens, 30+ components, layout, theming, M3 Expressive (platform matrix), and accessibility. Use when: "material design", "MD3", "material you", "Jetpack Compose", "MaterialTheme", "material component", "md3 button".4---5
6# Material Design 3
7
8This skill guides implementation of Google's Material Design 3 (MD3) — a personal, adaptive, expressive design system. MD3 uses dynamic color, tonal surfaces, rounded shapes, and spring-based motion to create UIs that feel alive and personal.
9
10## Philosophy
11
12MD3 is built on three principles:
13- **Personal**: Dynamic color adapts UI to the user's wallpaper or content. Theming is individual, not one-size-fits-all.
14- **Adaptive**: Layouts transform across 5 window size classes. Components resize, reposition, and change form factor responsively.
15- **Expressive**: Shape morphing, spring physics, and emphasized typography create moments of delight without sacrificing usability.
16
17## Current Updates: Google I/O 2026
18
19Material's [Google I/O 2026 update](https://m3.material.io/blog/whats-new-at-io26) reinforces a **Compose-first** Android path and expands expressive/adaptive guidance:
20
21- **Material Android is Compose-first**: For new Android work, prefer Jetpack Compose Material3 for the latest components, expressive APIs, adaptive scaffolds, and Styles API integration. Android Views may remain necessary in existing apps, but they should not be treated as the default path for new Material 3 implementations.
22- **Expressive layout system**: Use an expressive layout scaffold to adapt screens across mobile, desktop, foldables, watches, XR, and other spatial form factors. Start from adaptive scaffolds/window size classes instead of fixed phone-first layouts.
23- **8dp spacing system**: Apply spacing tokens for margins, padding, and gaps so layouts and components can adapt programmatically to device type and density.
24- **New/updated expressive components**: Lists, menus, search, and search app bars have refreshed expressive guidance, with Jetpack Compose as the primary implementation target.
25- **Watches and XR**: Watches emphasize physics-based motion, arc text, and edge-hugging containers. XR emphasizes spatial panels and depth-based elevation.
26
27**Key differences from MD2:**
28- Tonal surfaces replace elevation shadows as the primary depth cue
29- Dynamic color generates full schemes from a single seed color
30- Fully rounded corners by default (not slightly rounded)
31- Spring-based motion physics replace fixed easing curves for components
32- 3 levels of user-controlled contrast (standard/medium/high)
33
34**Relationship with frontend-design skill:**
35When both skills are active, MD3 provides the design system (tokens, components, layout rules) and frontend-design provides creative direction within those constraints. MD3 rules take precedence for component structure and token usage. Note: Roboto/Roboto Flex IS the correct default typeface in MD3 — the frontend-design guidance to avoid Roboto does not apply when implementing MD3.
36
37## Decision Tree
38
39**What are you building?**
40```
41Full app scaffold → See "Common Patterns: App Shell" + references/layout-and-responsive.md
42Single component → See "Component Quick Reference" table → references/component-catalog.md
43Custom theme → See references/theming-and-dynamic-color.md
44Form / input layout → See references/component-catalog.md § Input Components
45Navigation structure → See references/navigation-patterns.md
46Data display → See references/component-catalog.md § Data Display
47```
48
49**What platform?**
50```
51Jetpack Compose → Primary: androidx.compose.material3, MaterialTheme, references/*
52Flutter → useMaterial3: true in ThemeData, ColorScheme.fromSeed()
53Web (vanilla JS) → @material/web (limited; maintenance mode) + CSS custom properties
54Web (React/Vue/Svelte) → CSS custom properties + wrapper components (no official React lib)
55Web (CSS-only) → MD3 token values as CSS custom properties (no <md-*> elements)
56```
57
58## Design Token System
59
60All MD3 tokens use the `md.sys` namespace. **Jetpack Compose** maps roles to `MaterialTheme.colorScheme`, `MaterialTheme.typography`, and `MaterialTheme.shapes` (same semantic roles as the spec). **On the web**, these map to CSS custom properties (`--md-sys-*`):
61
62### Color Tokens (`--md-sys-color-*`)
63| Token | Purpose |
64|-------|---------|
65| `primary` | High-emphasis fills, text, icons against surface |
66| `on-primary` | Text/icons on primary |
67| `primary-container` | Standout fill for key components (FAB, etc.) |
68| `on-primary-container` | Text/icons on primary-container |
69| `secondary` / `on-secondary` | Less prominent accents |
70| `secondary-container` / `on-secondary-container` | Recessive components (tonal buttons) |
71| `tertiary` / `on-tertiary` | Contrasting accents |
72| `tertiary-container` / `on-tertiary-container` | Complementary containers |
73| `error` / `on-error` | Error states (static — doesn't change with dynamic color) |
74| `error-container` / `on-error-container` | Error container fills |
75| `surface` | Default background |
76| `on-surface` | Text/icons on any surface |
77| `on-surface-variant` | Lower-emphasis text/icons on surface |
78| `surface-container-lowest` | Lowest-emphasis container |
79| `surface-container-low` | Low-emphasis container |
80| `surface-container` | Default container (nav areas) |
81| `surface-container-high` | High-emphasis container |
82| `surface-container-highest` | Highest-emphasis container |
83| `surface-dim` / `surface-bright` | Maintain relative brightness across light/dark |
84| `inverse-surface` / `inverse-on-surface` / `inverse-primary` | Contrasting elements (snackbars) |
85| `outline` | Important boundaries (text field borders) |
86| `outline-variant` | Decorative elements (dividers) |
87
88Full details: `references/color-system.md`
89
90### Typography Tokens (`--md-sys-typescale-*`)
91| Scale | Sizes | Use |
92|-------|-------|-----|
93| Display | L / M / S | Hero text, large numbers |
94| Headline | L / M / S | Section headers |
95| Title | L / M / S | Smaller headers, card titles |
96| Body | L / M / S | Paragraph text, descriptions |
97| Label | L / M / S | Buttons, chips, captions |
98
99Each style has tokens for: `-font`, `-weight`, `-size`, `-line-height`, `-tracking`
100Plus 15 **emphasized** variants (higher weight) via `--md-sys-typescale-emphasized-*`
101
102Full details: `references/typography-and-shape.md`
103
104### Shape Tokens (`--md-sys-shape-corner-*`)
105| Token | Value | Example components |
106|-------|-------|-------------------|
107| `none` | 0dp | — |
108| `extra-small` | 4dp | Chips, snackbars |
109| `small` | 8dp | Text fields, menus |
110| `medium` | 12dp | Cards |
111| `large` | 16dp | FABs, navigation drawer |
112| `large-increased` | 20dp | (Expressive) |
113| `extra-large` | 28dp | Dialogs, bottom sheets |
114| `extra-large-increased` | 32dp | (Expressive) |
115| `extra-extra-large` | 48dp | (Expressive) |
116| `full` | 9999px | Buttons, chips, badges |
117
118### Elevation Levels
119| Level | DP | Tonal offset | Use |
120|-------|-----|-------------|-----|
121| 0 | 0dp | None | Flat surfaces, most components at rest |
122| 1 | 1dp | +5% primary | Elevated cards, modal sheets |
123| 2 | 3dp | +8% primary | Menus, nav bar, scrolled app bar |
124| 3 | 6dp | +11% primary | FAB, dialogs, search, date/time pickers |
125| 4 | 8dp | +12% primary | (hover/focus increase only) |
126| 5 | 12dp | +14% primary | (hover/focus increase only) |
127
128Elevation in MD3 is communicated through **tonal surface color**, not shadows. Shadows are only used when needed for additional protection against busy backgrounds.
129
130### Motion
131MD3 Expressive (May 2025) introduced **spring-based motion physics** for components. The legacy easing/duration system is still used for **transitions** (enter/exit/shared-axis):
132
133| Easing | Duration | Transition type |
134|--------|----------|-----------------|
135| Emphasized | 500ms | Begin and end on screen |
136| Emphasized decelerate | 400ms | Enter the screen |
137| Emphasized accelerate | 200ms | Exit the screen |
138| Standard | 300ms | Begin and end on screen (utility) |
139| Standard decelerate | 250ms | Enter screen (utility) |
140| Standard accelerate | 200ms | Exit screen (utility) |
141
142CSS easing values:
143- Emphasized: `cubic-bezier(0.2, 0, 0, 1)`
144- Emphasized decelerate: `cubic-bezier(0.05, 0.7, 0.1, 1)`
145- Emphasized accelerate: `cubic-bezier(0.3, 0, 0.8, 0.15)`
146- Standard: `cubic-bezier(0.2, 0, 0, 1)`
147- Standard decelerate: `cubic-bezier(0, 0, 0, 1)`
148- Standard accelerate: `cubic-bezier(0.3, 0, 1, 1)`
149
150## Component Quick Reference
151
152| Component | Web Element | Key Variants | Category |
153|-----------|------------|--------------|----------|
154| Button | `md-filled-button`, `md-outlined-button`, `md-text-button`, `md-elevated-button`, `md-filled-tonal-button` | Filled, Outlined, Text, Elevated, Tonal; 5 sizes (XS–XL); toggle | Actions |
155| Button group | `md-button-group` | Standard, connected | Actions |
156| Extended FAB | `md-extended-fab` | Surface, Primary, Secondary, Tertiary | Actions |
157| FAB | `md-fab` | Small, Medium, Large | Actions |
158| FAB menu | — | — | Actions |
159| Icon button | `md-icon-button`, `md-filled-icon-button`, `md-filled-tonal-icon-button`, `md-outlined-icon-button` | Standard, Filled, Filled Tonal, Outlined | Actions |
160| Segmented button | — | Single-select, Multi-select | Actions |
161| Split button | — | — | Actions |
162| Badge | — | Small (dot), Large (count) | Communication |
163| Loading indicator | — | Linear, Circular | Communication |
164| Progress indicator | `md-linear-progress`, `md-circular-progress` | Linear, Circular; determinate/indeterminate | Communication |
165| Snackbar | — | Single-line, Two-line, Action | Communication |
166| Tooltip | — | Plain, Rich | Communication |
167| Card | — | Filled, Outlined, Elevated | Containment |
168| Carousel | — | Multi-browse, Uncontained, Hero | Containment |
169| Dialog | `md-dialog` | Basic, Full-screen | Containment |
170| Bottom sheet | — | Standard, Modal | Sheets |
171| Side sheet | — | Standard, Modal | Sheets |
172| Divider | `md-divider` | Full-width, Inset | Containment |
173| Checkbox | `md-checkbox` | — | Input |
174| Chips | `md-chip-set`, `md-assist-chip`, `md-filter-chip`, `md-input-chip`, `md-suggestion-chip` | Assist, Filter, Input, Suggestion | Input |
175| Date picker | — | Docked, Modal, Range | Input |
176| Menu | `md-menu`, `md-menu-item` | — | Input |
177| Radio button | `md-radio` | — | Input |
178| Slider | `md-slider` | Continuous, Discrete, Range | Input |
179| Switch | `md-switch` | With/without icon | Input |
180| Text field | `md-filled-text-field`, `md-outlined-text-field` | Filled, Outlined | Input |
181| Time picker | — | Docked, Modal | Input |
182| App bar (top) | — | Center-aligned, Small, Medium, Large | Navigation |
183| Navigation bar | `md-navigation-bar` | — | Navigation |
184| Navigation drawer | `md-navigation-drawer` | Standard, Modal | Navigation |
185| Navigation rail | — | — | Navigation |
186| Search | — | Search bar, Search view | Navigation |
187| Tabs | `md-tabs`, `md-primary-tab`, `md-secondary-tab` | Primary, Secondary | Navigation |
188| Toolbar | — | — | Navigation |
189| List | `md-list`, `md-list-item` | One-line, Two-line, Three-line | Data Display |
190
191**Note:** Components marked with `—` for web element don't have @material/web implementations yet. Use CSS custom properties with standard HTML for these. **Compose** mappings and examples live in `references/component-catalog.md`.
192
193Full component details with code examples: `references/component-catalog.md`
194
195## Jetpack Compose (primary)
196
197Use **`androidx.compose.material3`** with `MaterialTheme` and Material 3 composables (`Scaffold`, `Button`, `NavigationBar`, top app bars, etc.).
198
199- **Theming**: `MaterialTheme(colorScheme = …, typography = …, shapes = …)`. Prefer `dynamicLightColorScheme` / `dynamicDarkColorScheme` on **Android 12+ (API 31+)** when dynamic color is desired; otherwise `lightColorScheme` / `darkColorScheme` or generated theme code from Material Theme Builder.
200- **Adaptive UI**: Window size classes, list-detail and supporting-pane layouts, foldables — see `references/layout-and-responsive.md` and `references/navigation-patterns.md`.
201- **Edge-to-edge & insets**: Lay out content with `WindowInsets` / scaffold padding so bars and IME behave correctly — see `references/layout-and-responsive.md`.
202- **Experimental APIs**: Some Material 3 APIs require `@OptIn(ExperimentalMaterial3Api::class)` or expressive opt-ins; match your BOM and compiler.
203
204```kotlin
205MaterialTheme(
206 colorScheme = colorScheme, // from dynamicLightColorScheme / lightColorScheme / etc.
207 typography = Typography(),
208 shapes = Shapes(),
209) {
210 // M3 content — prefer references for Scaffold, navigation, text fields
211}
212```
213
214## Web (limited): @material/web
215
216**Important:** Per [Material Design 3 for Web](https://m3.material.io/develop/web), **Material Web Components are in maintenance mode** and **M3 Expressive is not implemented on Web**. Use `@material/web` for token-backed web UIs when appropriate, but do not treat it as equivalent to Compose for current Expressive features.
217
218### Setup
219
220```bash
221npm install @material/web
222```
223
224### Import Components Individually
225
226Always import only the components you use — importing the entire package bloats the bundle:
227
228```javascript
229// Good — individual imports
230import '@material/web/button/filled-button.js';
231import '@material/web/button/outlined-button.js';
232import '@material/web/textfield/outlined-text-field.js';
233import '@material/web/icon/icon.js';
234
235// Bad — never do this
236import '@material/web'; // imports everything
237```
238
239### Basic Usage
240
241```html
242<!DOCTYPE html>
243<html lang="en">
244<head>
245 <meta charset="UTF-8">
246 <meta name="viewport" content="width=device-width, initial-scale=1.0">
247 <link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@400;500;700&display=swap" rel="stylesheet">
248 <link href="https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined" rel="stylesheet">
249</head>
250<body>
251 <md-filled-button>Get started</md-filled-button>
252 <md-outlined-text-field label="Email" type="email"></md-outlined-text-field>
253
254 <script type="module">
255 import '@material/web/button/filled-button.js';
256 import '@material/web/textfield/outlined-text-field.js';
257 </script>
258</body>
259</html>
260```
261
262### Theming with CSS Custom Properties
263
264Apply a custom theme by setting CSS custom properties on `:root` or any ancestor:
265
266```css
267:root {
268 /* Color scheme (generate with @material/material-color-utilities) */
269 --md-sys-color-primary: #6750A4;
270 --md-sys-color-on-primary: #FFFFFF;
271 --md-sys-color-primary-container: #EADDFF;
272 --md-sys-color-on-primary-container: #21005D;
273 --md-sys-color-secondary: #625B71;
274 --md-sys-color-on-secondary: #FFFFFF;
275 --md-sys-color-secondary-container: #E8DEF8;
276 --md-sys-color-on-secondary-container: #1D192B;
277 --md-sys-color-surface: #FEF7FF;
278 --md-sys-color-on-surface: #1D1B20;
279 --md-sys-color-surface-container: #F3EDF7;
280 --md-sys-color-outline: #79747E;
281 --md-sys-color-outline-variant: #CAC4D0;
282
283 /* Typography */
284 --md-sys-typescale-body-large-font: 'Roboto Flex', sans-serif;
285 --md-sys-typescale-body-large-size: 1rem;
286 --md-sys-typescale-body-large-weight: 400;
287 --md-sys-typescale-body-large-line-height: 1.5rem;
288
289 /* Shape */
290 --md-sys-shape-corner-full: 9999px;
291 --md-sys-shape-corner-medium: 12px;
292}
293```
294
295### Component-Level Overrides
296
297Override individual component tokens for specific customization:
298
299```css
300md-filled-button {
301 --md-filled-button-container-color: var(--md-sys-color-primary);
302 --md-filled-button-label-text-color: var(--md-sys-color-on-primary);
303 --md-filled-button-container-shape: var(--md-sys-shape-corner-full);
304 --md-filled-button-container-height: 40px;
305}
306
307md-outlined-text-field {
308 --md-outlined-text-field-container-shape: var(--md-sys-shape-corner-small);
309 --md-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);
310}
311```
312
313### Dark Theme
314
315Apply dark theme by overriding color tokens on a class or media query:
316
317```css
318@media (prefers-color-scheme: dark) {
319 :root {
320 --md-sys-color-primary: #D0BCFF;
321 --md-sys-color-on-primary: #381E72;
322 --md-sys-color-primary-container: #4F378B;
323 --md-sys-color-on-primary-container: #EADDFF;
324 --md-sys-color-surface: #141218;
325 --md-sys-color-on-surface: #E6E0E9;
326 --md-sys-color-surface-container: #211F26;
327 --md-sys-color-outline: #938F99;
328 --md-sys-color-outline-variant: #49454F;
329 }
330}
331```
332
333Full theming guide: `references/theming-and-dynamic-color.md`
334
335## Common Patterns
336
337### App Shell
338
339Standard MD3 app with responsive navigation + top app bar + content area:
340
341```html
342<div class="md3-app">
343 <nav class="md3-nav-rail" aria-label="Main navigation">
344 <!-- Navigation rail for medium+ screens -->
345 <md-fab size="small" aria-label="Compose">
346 <md-icon slot="icon">edit</md-icon>
347 </md-fab>
348 <md-navigation-bar>
349 <md-navigation-tab label="Home">
350 <md-icon slot="active-icon">home</md-icon>
351 <md-icon slot="inactive-icon">home</md-icon>
352 </md-navigation-tab>
353 <md-navigation-tab label="Search">
354 <md-icon slot="active-icon">search</md-icon>
355 <md-icon slot="inactive-icon">search</md-icon>
356 </md-navigation-tab>
357 </md-navigation-bar>
358 </nav>
359 <main class="md3-content">
360 <header class="md3-top-app-bar">
361 <h1 class="md3-top-app-bar__title" style="font: var(--md-sys-typescale-title-large)">
362 Page Title
363 </h1>
364 </header>
365 <div class="md3-body">
366 <!-- Content here -->
367 </div>
368 </main>
369</div>
370```
371
372```css
373.md3-app {
374 display: flex;
375 min-height: 100vh;
376 background: var(--md-sys-color-surface);
377 color: var(--md-sys-color-on-surface);
378}
379
380.md3-nav-rail {
381 width: 80px;
382 background: var(--md-sys-color-surface);
383 border-right: 1px solid var(--md-sys-color-outline-variant);
384 display: flex;
385 flex-direction: column;
386 align-items: center;
387 padding-top: 12px;
388 gap: 12px;
389}
390
391.md3-content {
392 flex: 1;
393 display: flex;
394 flex-direction: column;
395}
396
397.md3-top-app-bar {
398 height: 64px;
399 padding: 0 16px;
400 display: flex;
401 align-items: center;
402 background: var(--md-sys-color-surface);
403}
404
405.md3-body {
406 padding: 24px;
407 flex: 1;
408}
409
410/* Responsive: switch to bottom nav on compact */
411@media (max-width: 599px) {
412 .md3-app { flex-direction: column; }
413 .md3-nav-rail {
414 order: 1;
415 width: 100%;
416 flex-direction: row;
417 justify-content: center;
418 border-right: none;
419 border-top: 1px solid var(--md-sys-color-outline-variant);
420 padding: 0;
421 }
422}
423```
424
425### Card Grid
426
427```html
428<div class="md3-card-grid">
429 <div class="md3-card md3-card--outlined">
430 <img src="image.jpg" alt="Description" class="md3-card__media">
431 <div class="md3-card__content">
432 <h3 style="font: var(--md-sys-typescale-title-medium)">Card Title</h3>
433 <p style="font: var(--md-sys-typescale-body-medium); color: var(--md-sys-color-on-surface-variant)">
434 Supporting text for this card.
435 </p>
436 </div>
437 <div class="md3-card__actions">
438 <md-text-button>Learn more</md-text-button>
439 <md-filled-tonal-button>Action</md-filled-tonal-button>
440 </div>
441 </div>
442</div>
443```
444
445```css
446.md3-card-grid {
447 display: grid;
448 grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
449 gap: 16px;
450}
451
452.md3-card--outlined {
453 border: 1px solid var(--md-sys-color-outline-variant);
454 border-radius: var(--md-sys-shape-corner-medium, 12px);
455 background: var(--md-sys-color-surface);
456 overflow: hidden;
457}
458
459.md3-card__content { padding: 16px; }
460.md3-card__actions { padding: 8px 16px 16px; display: flex; gap: 8px; justify-content: flex-end; }
461.md3-card__media { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
462```
463
464### Form Layout
465
466```html
467<form class="md3-form">
468 <md-outlined-text-field label="Full name" required></md-outlined-text-field>
469 <md-outlined-text-field label="Email" type="email" required></md-outlined-text-field>
470 <md-outlined-text-field label="Message" type="textarea" rows="4"></md-outlined-text-field>
471 <div class="md3-form__actions">
472 <md-text-button type="reset">Cancel</md-text-button>
473 <md-filled-button type="submit">Submit</md-filled-button>
474 </div>
475</form>
476```
477
478```css
479.md3-form {
480 display: flex;
481 flex-direction: column;
482 gap: 16px;
483 max-width: 560px;
484}
485
486.md3-form__actions {
487 display: flex;
488 gap: 8px;
489 justify-content: flex-end;
490 margin-top: 8px;
491}
492```
493
494More patterns: `references/navigation-patterns.md`, `references/layout-and-responsive.md`
495
496## Anti-Patterns
497
498**Never do these when implementing MD3:**
499
500- **Mix MD2 and MD3 libraries**: Don't use `@material/mdc-*` (MD2) alongside `@material/web` (MD3). They have incompatible APIs and styling.
501- **Hardcode colors**: Always use `var(--md-sys-color-*)` tokens, never raw hex/rgb values. Hardcoded colors break dynamic theming, dark mode, and contrast adjustment.
502- **Ignore tonal pairing**: Only combine colors in their intended pairs (e.g., `primary` + `on-primary`, `surface-container` + `on-surface`). Arbitrary pairings break contrast in dynamic color and high contrast modes.
503- **Use `outline` for dividers**: Use `outline-variant` for dividers. `outline` is for important boundaries like text field borders.
504- **Import all of @material/web**: Always import individual component modules. Barrel imports include every component and destroy bundle size.
505- **Use `border-radius` directly**: Use shape tokens (`var(--md-sys-shape-corner-medium)`) so shapes stay consistent with theming.
506- **Use shadows for elevation by default**: MD3 communicates elevation through tonal surface color, not shadows. Only add shadows when elements need extra separation from busy backgrounds.
507- **Apply frontend-design "avoid Roboto" rule**: On **Android**, **Roboto** is the default Material typeface; **web** often uses Roboto or Roboto Flex with MD3 tokens. Replace only when intentionally customizing the type scale.
508- **Assume SSR compatibility**: `@material/web` uses Web Components (custom elements) which require JavaScript to render. They won't produce meaningful HTML in SSR without additional hydration strategies.
509- **Ignore foldables and large screens**: MD3 is designed for all screen sizes. Don't ship phone-only layouts — use canonical layouts, multi-pane at 600dp+, and test on foldable/tablet emulators. Place no interactive content across the fold/hinge.
510- **Stretch content to fill wide screens**: On Large (1200dp+) and Extra-large (1600dp+) windows, constrain content to a max width (840–1040dp). Endless-width text lines are unreadable.
511
512## Platform Notes
513
514### Flutter
515```dart
516MaterialApp(
517 theme: ThemeData(
518 useMaterial3: true,
519 colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
520 ),
521);
522```
523
524### Jetpack Compose
525See **[Jetpack Compose (primary)](#jetpack-compose-primary)** above. Use `LocalContext.current` with `dynamicLightColorScheme` / `dynamicDarkColorScheme` only when `Build.VERSION.SDK_INT >= Build.VERSION_CODES.S` and dynamic color is enabled; otherwise supply static light/dark schemes.
526
527### Component Name Mapping
528| Concept | Web | Flutter | Compose |
529|---------|-----|---------|---------|
530| Filled button | `md-filled-button` | `FilledButton` | `Button` |
531| Outlined text field | `md-outlined-text-field` | `OutlinedTextField` | `OutlinedTextField` |
532| FAB | `md-fab` | `FloatingActionButton` | `FloatingActionButton` |
533| Navigation bar | `md-navigation-bar` | `NavigationBar` | `NavigationBar` |
534| Switch | `md-switch` | `Switch` | `Switch` |
535
536## M3 Expressive (May 2025)
537
538The Expressive update adds visual richness while maintaining usability. **Availability differs by platform** — do not assume one stack implements everything.
539
540| Capability | Jetpack Compose | Flutter | Web (`@material/web`) |
541|------------|-----------------|---------|------------------------|
542| Expressive layout scaffold / adaptive layout | Compose-first via Material3 adaptive APIs and window size classes | Use Flutter adaptive/layout primitives | CSS/container queries/manual layout; no Material Web parity |
543| 8dp spacing system | Use design tokens / `Dp` spacing constants; keep margins, padding, and gaps adaptive | Use theme spacing constants | CSS custom properties / design tokens |
544| Expressive lists, menus, search, search app bar | Primary target per current Material guidance; check BOM and opt-ins | Check current Flutter Material docs | Spec-aligned custom implementation; `@material/web` is maintenance-only |
545| Spring / motion physics | Supported in Material 3 (see `MotionScheme`, expressive APIs per BOM) | Varies by Flutter Material version | **Not** in Material Web; use easing/duration or custom motion |
546| Emphasized typography | Via theme / type scale | Via theme | Token/CSS only; no full Expressive component set |
547| Shape morphing | Compose-first in Google’s expressive rollout | Check current Flutter docs | **Not** in `@material/web` |
548| New button sizes (XS–XL), toggle | Follow Compose Material3 components | Follow Flutter MD3 | Height/CSS approximations only |
549| Extra corner tokens (e.g. large-increased) | `MaterialTheme.shapes` / tokens | Theme shapes | CSS `--md-sys-shape-*` |
550| 3 contrast levels | Scheme builders / system | Plugins / manual | `SchemeContent` contrast parameter in JS utilities |
551| Watches / XR form factors | Use Compose/Wear/XR-specific guidance where available | Platform-specific | Web/spatial UI custom implementation |
552
553**Web:** [Material Web is maintenance-only; M3 Expressive is not on Web](https://m3.material.io/develop/web). Use CSS easing/duration tokens as fallback for motion, not spring parity.
554
555**Legacy easing/duration** remains valid for **transitions** (enter/exit/shared-axis) where the spec still references them; see the Motion table below.
556
557## MD3 Compliance Audit
558
559When invoked with `audit` as the argument (e.g., `/material-3 audit`), or when asked to audit/review MD3 compliance, analyze the target app or page and produce a compliance report.
560
561### Audit Procedure
562
5631. **Identify the target**: The user provides a URL (use browser tools to inspect), file paths (read source), or a running app.
5642. **Inspect the following categories** and score each 0–10:
565
566| Category | What to check |
567|----------|--------------|
568| **Color tokens** | **Web:** `--md-sys-color-*` / generated CSS. **Compose:** `MaterialTheme.colorScheme` roles (no arbitrary `Color(...)` for surfaces without reason). Proper tonal pairing (`onX` on `X`). Dark theme. **Flutter:** `ColorScheme` roles. |
569| **Typography** | MD3 type scale: **Compose** `MaterialTheme.typography`; **web** typescale tokens; correct roles (Display, Headline, Title, Body, Label). |
570| **Shape** | **Compose** `MaterialTheme.shapes` / component `Shape`; **web** `var(--md-sys-shape-*)`. Buttons: full; cards: medium; avoid magic numbers. |
571| **Elevation** | Tonal elevation (`Surface` tonal/shadow as appropriate). **Web:** hover/focus where relevant. |
572| **Components** | **Compose:** Material3 composables (`Button`, `Scaffold`, etc.). **Web:** `@material/web` or spec-aligned HTML/CSS. Correct variants. |
573| **Layout** | Canonical layouts; **Compose** window size class / adaptive APIs; readable max width on large widths; foldable hinge avoidance. |
574| **Navigation** | Bar / rail / drawer / drawers+**Compose** `NavHost` patterns per size class; predictive back where applicable. |
575| **Motion** | **Compose** `MotionScheme` / expressive APIs when used; transitions may still use easing/duration. **Web:** CSS motion tokens fallback. |
576| **Accessibility** | MD3 roles help, but **verify contrast**: UI components often need **3:1** for large text/borders and **4.5:1** for normal text (WCAG 2.x). TalkBack/semantics (Compose), focus order, touch targets (~48dp). **Web:** ARIA, keyboard. |
577| **Theming** | **Compose:** `MaterialTheme` + light/dark/dynamic as designed. **Web:** CSS custom properties on `:root` or subtree. **Flutter:** `ThemeData` + `ColorScheme`. |
578
5793. **Generate the report**:
580
581```
582# MD3 Compliance Audit Report
583
584Target: [URL or file path]
585Date: [date]
586Overall Score: [X/100]
587
588## Scores by Category
589| Category | Score | Status |
590|----------------|-------|--------|
591| Color tokens | X/10 | [pass/warn/fail] |
592| Typography | X/10 | [pass/warn/fail] |
593| Shape | X/10 | [pass/warn/fail] |
594| Elevation | X/10 | [pass/warn/fail] |
595| Components | X/10 | [pass/warn/fail] |
596| Layout | X/10 | [pass/warn/fail] |
597| Navigation | X/10 | [pass/warn/fail] |
598| Motion | X/10 | [pass/warn/fail] |
599| Accessibility | X/10 | [pass/warn/fail] |
600| Theming | X/10 | [pass/warn/fail] |
601
602## Critical Issues
603[List items scoring 0-3 with specific file:line references and fixes]
604
605## Warnings
606[List items scoring 4-6 with recommendations]
607
608## Passing
609[List items scoring 7-10 with notes on what's done well]
610
611## Recommended Fixes (Priority Order)
6121. [Most impactful fix first]
6132. ...
614```
615
616### Audit Methods
617
618**For a live URL** (browser or devtools):
619- Inspect computed styles and CSS variables (`--md-sys-*`)
620- Resize viewport or use responsive mode for breakpoints
621- Capture screenshots at key widths if helpful
622
623**For source code** (file paths provided):
624- **Compose/Kotlin:** `.kt` files — `MaterialTheme`, composables, `Color(0x…)` abuse, hard-coded `Dp`, missing `Modifier.semantics` where needed
625- **Flutter:** `.dart` — `ThemeData`, `ColorScheme`
626- **Web:** HTML/JSX/Vue/Svelte; CSS/SCSS for tokens
627- Check **web** imports for `@material/web` vs `@material/mdc-*` (MD2)
628
629**Quick checks** (adapt paths to your stack):
630```
631# Web: hardcoded colors
632grep -rn '#[0-9a-fA-F]\{3,8\}' --include='*.css' --include='*.scss'
633
634# Compose: raw Color(...) audits (sample — tune for your codebase)
635grep -rn 'Color(0x' --include='*.kt'
636
637# MD2 on web
638grep -rn '@material/mdc-' --include='*.js' --include='*.ts'
639```
640
641**Browser automation** (if your environment exposes MCP browser tools): navigate, snapshot DOM/CSS variables, resize for breakpoints — optional, not required.
642
643### Scoring Guide
644
645- **9-10**: Fully MD3 compliant, uses correct tokens and patterns
646- **7-8**: Mostly compliant, minor issues (e.g., a few hardcoded values)
647- **4-6**: Partially compliant, some MD3 patterns but significant gaps
648- **1-3**: Major violations, mostly non-MD3 or MD2 patterns
649- **0**: Not applicable or completely absent
650
651Status thresholds: **pass** (7+), **warn** (4-6), **fail** (0-3)
652
653## Reference Documents
654
655- `references/color-system.md` — Color roles, tonal palettes, dynamic color, Compose + CSS mapping
656- `references/typography-and-shape.md` — Type scale, shape corners, elevation, motion, Expressive notes
657- `references/component-catalog.md` — Components: Compose + `@material/web` where applicable
658- `references/navigation-patterns.md` — Navigation selection, Compose-first adaptive patterns
659- `references/layout-and-responsive.md` — Breakpoints, canonical layouts, insets, foldables
660- `references/theming-and-dynamic-color.md` — Theming: Compose first, then Flutter and web