Material Design 3 for Flutter
🎨 A complete Material Design 3 design system implementation for Flutter
A comprehensive design system toolkit that brings Google's Material Design 3 specifications to Flutter through a carefully architected token system.
🚀 Live Demo & Resources
🌟 Interactive Design System Explorer - Explore all tokens with live examples
📚 Material Design 3 Guidelines - Official specification
📦 Installation
dependencies:
material_design: ^0.28.0
🎯 Three Ways to Use This Library
✅ The Right Way: Material Design 3 Compliant
Use M3 wrapper classes that enforce design system rules while maintaining const performance.
// Best approach - follows M3 specs with const performance
// Motion example - impossible to mismatch
return AnimatedContainer(
duration: M3Motion.emphasized.duration, // Always correct pairing (non-const)
curve: M3Motion.emphasized.curve, // Follows M3 specs exactly (non-const)
// M3EdgeInsets enforces token usage + const
padding: const M3EdgeInsets.all(M3SpacingToken.space16), // (const)
// M3BoxDecoration ensures all properties follow M3
decoration: M3BoxDecoration(
borderRadius: M3BorderRadius.medium, // (const)
boxShadow: M3Elevation.level3.shadows, // (non-const)
color: M3Elevation.level3.surfaceColor(context), // (non-const)
),
child: const Text(
'Perfect M3 Implementation',
style: M3TextStyle.headlineMedium, // (const)
),
);
Why this is best:
- ✅ Forces Material Design 3 compliance
- ✅ Type-safe token usage
- ✅ Const performance where possible
- ✅ Impossible to break design system rules
⚠️ The Flexible Way: Trading Compliance for Freedom
Use const tokens directly with Flutter widgets. More flexible but can break M3 guidelines.
// Intermediate approach - flexible but can violate M3
Container(
// Using const tokens but might mix incorrectly
padding: const EdgeInsets.all(M3Spacings.space16), // (const)
decoration: const BoxDecoration(
borderRadius: M3BorderRadius.medium, // (const)
boxShadow: M3ElevationShadows.level3, // (const)
color: Colors.purple, // ⚠️ Missing surface tint. Not M3 surface color! (const)
),
child: const Text(
'Partial M3 Implementation',
style: M3TextStyle.headlineMedium, // (const)
),
);
// Motion example - easy to mismatch
AnimatedContainer(
duration: M3MotionDuration.long2, // ⚠️ Is this the right duration? (const)
curve: M3MotionCurve.standard, // ⚠️ Wrong curve for long2! (const)
);
Trade-offs:
- ⚠️ Can mix incompatible tokens
- ⚠️ May violate M3 specifications
- ✅ More flexibility for custom designs
- ✅ Still has const performance
❌ The Wrong Way: Worst of Both Worlds
Using token enums with .value
- loses const performance AND design system benefits.
// DON'T DO THIS - no benefits, only drawbacks
Container(
// ❌ Lost const performance
padding: EdgeInsets.all(M3SpacingToken.space16.value), // (non-const)
decoration: BoxDecoration(
// ❌ Still not const
borderRadius: BorderRadius.circular(M3CornerToken.medium.value), // (non-const)
// ❌ Can still break M3 rules
boxShadow: [
BoxShadow(
offset: const Offset(0, 2), // ❌ Random shadow values
blurRadius: M3SpacingToken.space4.value, // ❌ Why use spacing for blur?
),
],
),
child: Text(
'Worst Implementation',
// ❌ Mixing approaches inconsistently
style: TextStyle(fontSize: 17),
),
);
Why this is wrong:
- ❌ No const performance (using
.value
) - ❌ No design system enforcement
- ❌ Verbose without benefits
- ❌ Easy to misuse tokens
📊 Quick Reference
Design System Classes (Use These First)
Class | Purpose | Example |
---|---|---|
M3EdgeInsets |
Type-safe padding/margin with const | const M3EdgeInsets.all(M3SpacingToken.space16) |
M3BoxDecoration |
Complete M3 decoration | M3BoxDecoration(elevation: M3Elevation.level3) |
M3Gap |
Auto-directional spacing | M3Gap(M3SpacingToken.space16) |
M3Motion |
Paired duration + curve | M3Motion.emphasized |
M3Elevation |
Complete elevation concept | M3Elevation.level3 (includes dp, shadows, surfaceColor) |
Const Tokens (When You Need Flexibility)
Token | Values | Usage |
---|---|---|
M3Spacings |
space4 , space8 , space16 , space24 ... |
const EdgeInsets.all(M3Spacings.space16) |
M3BorderRadius |
small , medium , large ... |
BorderRadius: M3BorderRadius.medium |
M3ElevationShadows |
level0 to level5 |
boxShadow: M3ElevationShadows.level3 |
M3TextStyle |
displayLarge , bodyMedium ... |
style: M3TextStyle.headlineMedium |
Token Enums (Avoid Using .value)
⚠️ Avoid | Why | Use Instead |
---|---|---|
M3SpacingToken.space16.value |
Loses const | M3Spacings.space16 |
M3CornerToken.medium.value |
No benefit | M3Corners.medium |
M3OpacityToken.disabledContent.value |
Verbose | M3Opacities.disabledContent |
🎯 Summary
Choose Your Approach
- Need Material Design 3 compliance? → Use M3 wrapper classes
- Need flexibility with good performance? → Use const tokens directly
- Never do this → Don't use
.value
on token enums
Performance vs Compliance Matrix
Approach | M3 Compliance | Performance | Flexibility | Recommendation |
---|---|---|---|---|
M3 Classes | ✅ Perfect | ✅ Const where possible | ⚠️ Limited | Use this |
Const Tokens | ⚠️ Manual | ✅ Full const | ✅ High | Use when needed |
Token.value | ❌ None | ❌ No const | ⚠️ Medium | Avoid |
📊 Complete Token and Utility Reference
Design Tokens
These are constant values that form the foundation of your design system, ensuring consistency across spacing, colors, typography, and more.
🟢 CONST Design Tokens
Use these with const
keyword for best performance:
Group | Token | Class (const) | Purpose | Example Values | How to Use |
---|---|---|---|---|---|
Layout & Spacing | Spacing | M3Spacings |
4dp grid system for consistent spacing | space0 (0dp), space2 (2dp), space4 (4dp), space8 (8dp), space12 (12dp), space16 (16dp), space24 (24dp), space32 (32dp), space48 (48dp) |
const EdgeInsets.all(M3Spacings.space16) |
Margin | M3Margins |
Responsive container margins | compactScreen (16dp), mediumScreen (24dp), expandedScreen (32dp), largeScreen (40dp), extraLargeScreen (48dp) |
const EdgeInsets.symmetric(horizontal: M3Margins.compactScreen) |
|
Spacer | M3Spacers |
Pre-built spacer widgets | horizontal4 , horizontal8 , horizontal16 , vertical4 , vertical8 , vertical16 , etc. |
M3Spacers.horizontal16 |
|
Icon Size | M3IconSizes |
Standardized icon dimensions | extraSmall (18dp), small (20dp), medium (24dp), large (36dp), extraLarge (40dp), huge (48dp) |
Icon(Icons.star, size: M3IconSizes.medium) |
|
Visual Density | M3VisualDensity |
UI density configurations | minimumDensity (-3), compactDensity (-2), standardDensity (0), comfortableDensity (0) |
VisualDensity(horizontal: M3VisualDensity.standardDensity) |
|
Z-Index | M3ZIndexes |
Values for layer stacking order | behind (-1), base (0), dropdown (10), sticky (100), modal (1000), tooltip (9999) |
Positioned(child: widget, zIndex: M3ZIndexes.modal) |
|
Responsive | Breakpoint | M3Breakpoints |
Breakpoints for responsive design | compact (0dp), medium (600dp), expanded (840dp), large (1200dp), extraLarge (1600dp) |
if (width > M3Breakpoints.medium) ... |
Motion & Animation | Motion Duration | M3MotionDuration |
Duration for animations | short1 (50ms), short2 (100ms), short3 (150ms), short4 (200ms), medium1 (250ms), medium2 (300ms), medium3 (350ms), medium4 (400ms), long1 (450ms), long2 (500ms), long3 (550ms), long4 (600ms), extraLong1 (700ms), extraLong2 (800ms), extraLong3 (900ms), extraLong4 (1000ms) |
AnimatedContainer(duration: M3MotionDuration.medium1) |
Motion Curve | M3MotionCurve |
Easing curves for animations | emphasized , emphasizedAccelerate , emphasizedDecelerate , standard , standardAccelerate , standardDecelerate , linear |
AnimatedContainer(curve: M3MotionCurve.emphasized) |
|
Motion | M3Motion |
Combined duration + curve settings | emphasized , emphasizedIncoming , emphasizedOutgoing , standard , standardIncoming , standardOutgoing , linear |
See non-const section | |
Color & Opacity | Opacity | M3Opacities |
General transparency values | opacity4 (0.04), opacity8 (0.08), opacity12 (0.12), opacity16 (0.16), opacity38 (0.38), opacity54 (0.54), opacity87 (0.87) |
Opacity(opacity: M3Opacities.opacity38) |
State Layer | M3StateLayerOpacities |
Overlays for interactive states | hover (0.08), focus (0.12), pressed (0.12), dragged (0.16) |
Container(color: color.withOpacity(M3StateLayerOpacities.hover)) |
|
Shape & Border | Corner | M3Corners |
Individual corner values | none (0dp), extraSmall (4dp), small (8dp), medium (12dp), large (16dp), extraLarge (28dp), full (circular) |
Radius.circular(M3Corners.medium) |
Radius | M3Radius |
Individual corner radius values | none , extraSmall , small , medium , large , extraLarge , circular |
M3Radius.medium |
|
Border Radius | M3BorderRadius |
Complete border radius for containers | none , extraSmall , small , medium , large , extraLarge , full |
BoxDecoration(borderRadius: M3BorderRadius.medium) |
|
Shape | M3Shape |
Border shapes for components | none , extraSmall , small , medium , large , extraLarge , full |
Card(shape: M3Shape.medium) |
|
Border Width | M3BorderWidths |
Border thickness values | none (0dp), thin (1dp), medium (2dp), thick (4dp) |
Border.all(width: M3BorderWidths.thin) |
|
Border Side | M3BorderSide |
Individual border sides | Pre-configured border side configurations | M3BorderSide.thin(color) |
|
Border | M3Border |
Complete border specifications | Pre-configured borders | M3Border.all(color: Colors.grey) |
|
Elevation & Shadow | Elevation DP | M3ElevationDps |
Surface elevation values in dp | level0 (0dp), level1 (1dp), level2 (3dp), level3 (6dp), level4 (8dp), level5 (12dp) |
Material(elevation: M3ElevationDps.level3) |
Shadow | M3ElevationShadows |
Box shadow configurations | level0 , level1 , level2 , level3 , level4 , level5 |
BoxDecoration(boxShadow: M3ElevationShadows.level3) |
|
Elevation | M3Elevation |
Complete elevation (dp + shadows) | level0 , level1 , level2 , level3 , level4 , level5 - each contains both dp value and shadow list |
M3Elevation.level3 (access .dp and .shadows properties) |
|
Typography | Text Style | M3TextStyle |
Complete typography scale | displayLarge , displayMedium , displaySmall , headlineLarge , headlineMedium , headlineSmall , titleLarge , titleMedium , titleSmall , bodyLarge , bodyMedium , bodySmall , labelLarge , labelMedium , labelSmall |
Text('Hello', style: M3TextStyle.bodyLarge) |
🔵 NON-CONST Tokens (Enums and Functions)
Use these WITHOUT const
keyword - values calculated at runtime:
Group | Token | Enum/Function | Why it's not const | How to Use |
---|---|---|---|---|
Layout & Spacing | Spacing | M3SpacingToken |
Enum returns value via getter | final space = M3SpacingToken.space16.value; |
Margin | M3MarginToken |
Enum returns value via getter | final margin = M3MarginToken.compactScreen.value; |
|
Spacer | M3SpacerToken |
Enum returns widget via getter | M3SpacerToken.horizontal16.spacer |
|
Icon Size | M3IconSizeToken |
Enum returns value via getter | final size = M3IconSizeToken.medium.value; |
|
Z-Index | M3ZIndexToken |
Enum returns value via getter | final zIndex = M3ZIndexToken.modal.value; |
|
Responsive | Breakpoint | M3BreakpointToken |
Enum returns value via getter | final breakpoint = M3BreakpointToken.medium.value; |
Margin (method) | M3Margins.getMargin() |
Varies with screen size | final margin = M3Margins.getMargin(context); |
|
Motion & Animation | Motion | M3Motion.x.duration M3Motion.x.curve |
Object with duration and curve props | final motion = M3Motion.emphasized; duration: motion.duration, curve: motion.curve, |
Color & Opacity | Opacity | M3OpacityToken |
Enum returns value via getter | final opacity = M3OpacityToken.opacity38.value; |
State Layer | M3StateLayerOpacityToken |
Enum returns value via getter | final opacity = M3StateLayerOpacityToken.hover.value; |
|
Surface Tint | M3SurfaceTint.fromElevation() |
Depends on theme/context | final color = M3SurfaceTint.fromElevation(context, M3ElevationDps.level3); |
|
Shape & Border | Corner | M3CornerToken |
Enum returns value via getter | final corner = M3CornerToken.medium.value; |
Border Width | M3BorderWidthToken |
Enum returns value via getter | final width = M3BorderWidthToken.thin.value; |
|
Elevation & Shadow | Elevation | M3Elevation.x.dp M3Elevation.x.shadows M3Elevation.x.surfaceColor() |
Enum with multiple getters | final elev = M3Elevation.level3.value; final shadows = M3Elevation.level3.shadows; final surface = M3Elevation.level3.surfaceColor(context); |
Utility & Helper Classes
These are classes that help apply design tokens in a type-safe and responsive way.
Group | Utility / Class | Purpose | Common Use Case |
---|---|---|---|
Layout Helpers | M3EdgeInsets |
Type-safe padding/margin | Enforces use of spacing tokens |
M3Padding |
Pre-configured padding widget | Consistent padding application | |
M3Gap |
Spacing between flex children (Row/Column) | Row /Column spacing |
|
Decoration Helpers | M3BoxDecoration |
Type-safe box decoration | Enforces use of all style tokens |
M3ShapeDecoration |
Type-safe shape decoration | Enforces use of all style tokens | |
Responsive Builders | M3ResponsiveBuilder |
Responsive widget builder | Rebuilds on screen size class change |
M3ResponsiveValue |
Responsive value selection | Defines different values per breakpoint | |
M3ResponsiveVisibility |
Conditional visibility | Shows/hides based on screen size | |
M3ResponsiveGrid |
Responsive grid layout | Adaptive columns and spacing | |
M3ResponsiveScaffold |
Adaptive navigation scaffold | Bottom nav → Rail → Drawer | |
Responsive Logic | M3ScreenSize |
Window size classification | Compact, Medium, Expanded, etc. |
M3ResponsiveGridConfig |
Grid layout configuration | Columns, gutters, margins | |
M3ResponsiveNavigation |
Navigation pattern selection | Determines nav type by size |
📚 Further Reading
📄 License
BSD License - see LICENSE file
Building consistent, beautiful Flutter apps with Material Design 3
Libraries
- material_design
- A comprehensive toolkit for implementing Material Design 3 in Flutter.