Skip to content

Latest commit

 

History

History
1166 lines (951 loc) · 32.6 KB

File metadata and controls

1166 lines (951 loc) · 32.6 KB

🎨 Material 3 Expressive Design Guide

Your comprehensive guide to creating stunning, modern, and truly premium Android apps using Material Design 3 Expressive.

Last Updated: January 19, 2026
Author: Compiled for IvorMusic Project


📖 Table of Contents

  1. Introduction - What Makes M3 Expressive Special
  2. The 7 Emphasis Tactics
  3. Highlight Features
  4. Design Process & Tips from Designers
  5. Case Studies & Inspiration
  6. Implementation Guide
  7. Premium Design Checklist
  8. Resources & Links

Introduction - What Makes M3 Expressive Special

Material 3 Expressive isn't just an update—it's a philosophy shift. Released in May 2025 alongside Android 16, it represents Google's vision for design through the 2030s.

🎯 The Core Goal

"Make products more engaging, desirable, and user-friendly by fostering an emotional connection."

📊 Why It Matters (Research-Backed)

Google's research found that expressive designs:

  • Help users find key UI elements up to 4x faster
  • Are universally preferred by users across demographics
  • Improve perceived usability and satisfaction
  • Create stronger emotional connections with products

🌟 The Philosophy

Material 3 Expressive is about making interfaces feel:

  • Alive - Through physics-based motion
  • Personal - Through dynamic theming
  • Delightful - Through micro-interactions
  • Clear - Through visual hierarchy

The 7 Emphasis Tactics

These are the official design tactics from Google for creating expressive interfaces:

1. 🔷 Use a Variety of Shapes

Go beyond uniform shapes! Mix classic and abstract forms, combine round and square corner radii to create visual tension or cohesion.

// Mix different corner radii for visual interest
val heroCard = RoundedCornerShape(32.dp)     // Large, prominent
val actionButton = RoundedCornerShape(16.dp)  // Medium, interactive
val infoChip = RoundedCornerShape(8.dp)       // Small, subtle

2. 🎨 Apply Rich and Nuanced Colors

Use the full spectrum of Material's color roles. Mix primary, secondary, and tertiary colors strategically.

Role Usage Emphasis Level
Primary FABs, key CTAs Maximum
Secondary Filter chips, toggles Medium
Tertiary Badges, accents Complementary
Surface Variants Cards, depth Layering

3. 📝 Guide Attention with Typography

Use emphasized text styles—heavier weights, larger sizes, distinct colors, and adjusted spacing.

4. 📦 Contain Content for Emphasis

Organize content into logical groupings. Use cards and surfaces to:

  • Create clarity
  • Draw attention to specific elements
  • Make key actions stand out

5. 💫 Add Fluid and Natural Motion

Replace mechanical animations with physics-based motion using springs.

6. 🧩 Leverage Component Flexibility

Use the new, more configurable components with enhanced shape and motion options.

7. 🎭 Combine Tactics for "Hero Moments"

Layer multiple tactics together for key moments—like when a user completes an action or discovers a new feature.


Highlight Features

Variable Fonts & Emphasized Typography

What's New

Material 3 Expressive introduces visually emphasized typography through new type styles:

Style Standard Emphasized
Display displayLarge displayLargeEmphasized
Headline headlineMedium headlineMediumEmphasized
Title titleLarge titleLargeEmphasized
Body bodyLarge bodyLargeEmphasized
Label labelMedium labelMediumEmphasized

Emphasized Style Characteristics

  • Heavier weights (Black instead of Bold)
  • Larger optical sizes
  • Tighter letter spacing for headlines
  • More generous line height for body text

Variable Fonts: The Future

Roboto Flex and similar variable fonts allow:

  • Dynamic weight adjustment based on context
  • Size-specific optical adjustments
  • Device-aware legibility improvements
  • Single font file = multiple weights (better performance!)
// Using emphasized typography
Text(
    text = "Your Library",
    style = MaterialTheme.typography.headlineLarge.copy(
        fontWeight = FontWeight.Black,
        letterSpacing = (-0.5).sp
    )
)

// For body text - generous, readable
Text(
    text = "Discover new music tailored just for you",
    style = MaterialTheme.typography.bodyLarge.copy(
        lineHeight = 28.sp
    )
)

Recommended Fonts for Premium Feel

Font Characteristics Best For
Inter Clean, versatile, excellent legibility General UI
Outfit Geometric, modern, friendly Headlines
Plus Jakarta Sans Rounded, approachable Casual apps
Montserrat Classic, elegant Premium feel
Poppins Geometric, contemporary Modern apps

35 New Shapes + Shape Morphing

The New Shape Library

Material 3 Expressive includes 35 new abstract shapes beyond basic rounded rectangles:

  • Stars, flowers, clover shapes
  • Organic, nature-inspired forms
  • Geometric patterns
  • Pill and squircle variations

The MaterialShapes Class ⭐ NEW!

The MaterialShapes class in androidx.compose.material3 provides instant access to all 35 predefined shapes:

import androidx.compose.material3.MaterialShapes

// Access predefined shapes (returns RoundedPolygon)
val circleShape = MaterialShapes.Circle
val pillShape = MaterialShapes.Pill
val diamondShape = MaterialShapes.Diamond
val arrowShape = MaterialShapes.Arrow

Complete List of MaterialShapes

Category Shapes
Basic Circle, Square, Oval, Pill
Geometric Triangle, Diamond, Pentagon, Hexagon, Octagon
Directional Arrow, SemiCircle, Arch, Fan
Organic ClamShell, Flower, Clover, Leaf, Cookie
Decorative Slanted, Bun, Boom, Ghostish, Heart
Specialty SoftBurst, SunnyNew, VerySunny, FourPointStar, SixPointStar, EightPointStar
Plus more! 35 total unique shapes

Using MaterialShapes

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ExpressiveAvatar() {
    // Use a flower shape for profile avatar
    val flowerShape = remember {
        MaterialShapes.Flower.toShape()
    }
    
    Box(
        modifier = Modifier
            .size(80.dp)
            .clip(flowerShape)
            .background(MaterialTheme.colorScheme.primaryContainer)
    ) {
        AsyncImage(
            model = avatarUrl,
            contentDescription = "Profile",
            contentScale = ContentScale.Crop
        )
    }
}

Shape Morphing Between MaterialShapes

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable  
fun MorphingButton(isSelected: Boolean) {
    val startShape = MaterialShapes.Circle
    val endShape = MaterialShapes.SoftBurst
    
    val progress by animateFloatAsState(
        targetValue = if (isSelected) 1f else 0f,
        animationSpec = spring(Spring.DampingRatioMediumBouncy)
    )
    
    val morph = remember { Morph(startShape, endShape) }
    val morphedShape = morph.toShape(progress)
    
    Box(
        modifier = Modifier
            .size(56.dp)
            .clip(morphedShape)
            .background(
                if (isSelected) MaterialTheme.colorScheme.primary
                else MaterialTheme.colorScheme.surfaceVariant
            )
    )
}

Important Note

// MaterialShapes requires the experimental opt-in
@OptIn(ExperimentalMaterial3ExpressiveApi::class)

Shape Morphing

One of the most delightful new features—shapes can smoothly transition between forms:

// Enable built-in shape morphing on buttons
IconButton(
    onClick = { /* action */ },
    shapes = IconButtonDefaults.shapes(), // Magic happens here!
) {
    Icon(Icons.Default.PlayArrow, "Play")
}

10-Step Corner Radius Scale

The corner radius system is now more granular:

Token Value Use Case
None 0dp Sharp, technical
Extra Small 4dp Badges, tiny elements
Small 8dp Chips, text fields
Medium 12dp Standard cards
Large 16dp Prominent cards
Extra Large 20dp Featured elements
Extra Extra Large 28dp Hero cards
Full Round 32dp+ Pills, avatars

Custom Shapes with graphics-shapes Library

// Create a custom clover shape
val cloverPolygon = RoundedPolygon.star(
    numVerticesPerRadius = 4,
    innerRadius = 0.5f,
    rounding = CornerRounding(radius = 0.2f)
)

// Convert to Compose Shape for clipping
class PolygonShape(private val polygon: RoundedPolygon) : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = polygon.toPath().asComposePath()
        // Scale and position...
        return Outline.Generic(path)
    }
}

Animated Shape Morphing

// Animate between two shapes
val morphProgress by animateFloatAsState(
    targetValue = if (isExpanded) 1f else 0f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioMediumBouncy
    )
)

// Use morph progress to interpolate between shapes
val morph = remember { Morph(startShape, endShape) }
Canvas(modifier) {
    drawPath(
        path = morph.toPath(progress = morphProgress),
        color = color
    )
}

Physics-Based Motion System

The Big Change

Material 3 Expressive replaces the old easing + duration system with physics-based springs.

Old System New System
tween(300ms, easeInOut) spring(dampingRatio, stiffness)
Linear interpolation Natural physics simulation
Fixed duration Dynamic, responsive
Robotic feel Alive, organic feel

Motion Schemes

Expressive Scheme (Default)

  • Animations slightly overshoot their target
  • Creates a noticeable "bounce"
  • Perfect for hero moments, key interactions

Standard Scheme

  • Minimal bounce, restrained
  • Professional, functional feel
  • Better for frequent, utilitarian actions
// Configure motion scheme in your theme
MaterialTheme(
    motionScheme = MotionScheme.expressive() // or .standard()
) {
    // Your app content
}

Spring Parameters Cheat Sheet

Parameter What It Does
dampingRatio How quickly oscillation stops (higher = faster)
stiffness How fast/snappy the animation is
// Very bouncy (playful apps, games)
spring(dampingRatio = Spring.DampingRatioHighBouncy)

// Balanced bounce (most apps)
spring(dampingRatio = Spring.DampingRatioMediumBouncy)

// Subtle, professional
spring(dampingRatio = Spring.DampingRatioLowBouncy)

// No bounce, smooth settle
spring(dampingRatio = Spring.DampingRatioNoBouncy)

Stiffness Options

Spring.StiffnessHigh      // 10000f - Very fast, snappy
Spring.StiffnessMedium    // 1500f  - Moderate speed
Spring.StiffnessLow       // 200f   - Slow, gentle
Spring.StiffnessVeryLow   // 50f    - Very slow, dramatic

New Components

1. Split Button

A button with a primary action + dropdown for related options.

SplitButtonLayout(
    leadingButton = {
        FilledButton(
            onClick = { primaryAction() }
        ) {
            Text("Save")
        }
    },
    trailingButton = {
        FilledIconButton(
            onClick = { showMenu = true }
        ) {
            Icon(Icons.Default.ArrowDropDown, null)
        }
    }
)

2. FAB Menu

Replaces stacked FABs—expands to show 2-6 related actions.

FloatingActionButtonMenu(
    expanded = menuExpanded,
    button = {
        ToggleFloatingActionButton(
            checked = menuExpanded,
            onCheckedChange = { menuExpanded = it }
        ) {
            Icon(
                if (menuExpanded) Icons.Default.Close 
                else Icons.Default.Add,
                null
            )
        }
    }
) {
    FloatingActionButtonMenuItem(
        onClick = { /* action */ },
        icon = { Icon(Icons.Default.Photo, null) },
        text = { Text("Gallery") }
    )
    // More items...
}

3. Loading Indicator

A new expressive loading animation for short waits (<5 seconds).

LoadingIndicator(
    modifier = Modifier.size(48.dp)
)
// Features a looping shape-morph sequence of 7 Material shapes!

4. Button Groups

Replaces segmented buttons with connected button groups featuring shape morphing.

Row(
    horizontalArrangement = Arrangement.spacedBy(
        ButtonGroupDefaults.ConnectedSpaceBetween
    )
) {
    ToggleButton(
        checked = selected == 0,
        onCheckedChange = { selected = 0 },
        shapes = ButtonGroupDefaults.connectedLeadingButtonShapes()
    ) {
        Text("Day")
    }
    ToggleButton(
        checked = selected == 1,
        onCheckedChange = { selected = 1 },
        shapes = ButtonGroupDefaults.connectedMiddleButtonShapes()
    ) {
        Text("Week")
    }
    ToggleButton(
        checked = selected == 2,
        onCheckedChange = { selected = 2 },
        shapes = ButtonGroupDefaults.connectedTrailingButtonShapes()
    ) {
        Text("Month")
    }
}

5. Floating Toolbars

Flexible, undocked toolbars that can appear anywhere.

HorizontalFloatingToolbar(
    expanded = true,
    modifier = Modifier
        .align(Alignment.BottomCenter)
        .navigationBarsPadding()
        .padding(bottom = 20.dp)
) {
    // Your toolbar content
}

6. Carousel Components

Multi-browse and uncontained carousels with parallax effects.

HorizontalMultiBrowseCarousel(
    state = rememberCarouselState { items.size },
    preferredItemWidth = 200.dp,
    itemSpacing = 8.dp
) { index ->
    // Carousel item with automatic sizing and parallax
}

Dynamic Color Evolution

What's Improved

  • Broader color range for primary, secondary, and tertiary roles
  • More surface container variants for depth
  • Enhanced contrast options (Standard, Medium, High)
  • Better brand color integration for non-dynamic themes

Surface Container System

MaterialTheme.colorScheme.surface                   // Base
MaterialTheme.colorScheme.surfaceContainerLowest    // Recessed
MaterialTheme.colorScheme.surfaceContainerLow       // Slightly recessed
MaterialTheme.colorScheme.surfaceContainer          // Default cards
MaterialTheme.colorScheme.surfaceContainerHigh      // Elevated
MaterialTheme.colorScheme.surfaceContainerHighest   // Most prominent

Contrast Levels

Material 3 supports three contrast levels for accessibility:

Level Ratio Use Case
Standard Minimum WCAG Default, meets basic accessibility
Medium 3:1 Enhanced readability
High 7:1 Maximum clarity, reduced visual noise

Icon Background Technique

Create professional icon backgrounds with alpha color:

Box(
    modifier = Modifier
        .size(48.dp)
        .clip(RoundedCornerShape(14.dp))
        .background(accentColor.copy(alpha = 0.12f)), // 12% opacity
    contentAlignment = Alignment.Center
) {
    Icon(
        imageVector = icon,
        tint = accentColor, // Full opacity
        modifier = Modifier.size(26.dp)
    )
}

Design Tokens

Design tokens are the building blocks of Material 3. They ensure consistency across your entire design system.

What Are Design Tokens?

Tokens are named values that represent design decisions:

  • Colors → colorScheme.primary, colorScheme.surface
  • Typography → typography.headlineLarge, typography.bodyMedium
  • Shapes → shapes.medium, shapes.large
  • Spacing → Multiples of 8dp

Why They Matter

  1. Consistency - Same values everywhere
  2. Theming - Change one token, update everywhere
  3. Dynamic Color - Tokens enable wallpaper-based theming
  4. Accessibility - Easy to adjust for contrast needs

Using Tokens in Compose

// ✅ Use tokens
Text(
    color = MaterialTheme.colorScheme.onSurface,
    style = MaterialTheme.typography.bodyLarge
)

// ❌ Avoid hardcoded values
Text(
    color = Color.Black,  // Bad - ignores dark mode!
    fontSize = 16.sp      // Bad - ignores user font preferences!
)

Material Symbols Icons

Material 3 uses Material Symbols - a modern, variable icon set.

Key Features

  • Variable font technology - Single file, multiple styles
  • 4 adjustable axes:
    • Fill (0-1): Outlined ↔ Filled
    • Weight (100-700): Thin ↔ Bold
    • Grade (-25 to 200): Light ↔ Heavy emphasis
    • Optical Size (20-48): Adapts to display size

Icon Style Variants

Variant Characteristics Best For
Outlined Clean, minimal Default state
Rounded Friendly, approachable Most apps
Sharp Precise, technical Pro/developer tools
Filled Bold, prominent Selected/active states

In Compose - Use Rounded Icons

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*

// ✅ Rounded icons look more modern
Icon(Icons.Rounded.PlayArrow, "Play")
Icon(Icons.Rounded.Home, "Home")
Icon(Icons.Rounded.Settings, "Settings")

// Use Filled for selected states
Icon(
    if (isSelected) Icons.Filled.Home else Icons.Outlined.Home,
    "Home"
)

Icon Sizing Guidelines

Context Size Icon Token
Dense lists 20dp Small
Standard lists 24dp Default
Buttons 24dp Default
FABs 24-36dp Medium-Large
Navigation 24dp Default
Hero displays 48dp+ Large

Accessibility Guidelines

Material 3 Expressive is built with accessibility as a core value.

Motion Accessibility

Always respect the user's motion preferences:

@Composable
fun AccessibleAnimation() {
    // Check if user prefers reduced motion
    val reduceMotion = LocalReducedMotion.current
    
    val animationSpec = if (reduceMotion) {
        snap<Float>() // Instant, no animation
    } else {
        spring(dampingRatio = Spring.DampingRatioMediumBouncy)
    }
    
    val scale by animateFloatAsState(
        targetValue = targetScale,
        animationSpec = animationSpec
    )
}

Color Contrast Requirements

Element Minimum Ratio
Normal text 4.5:1
Large text (18sp+ or 14sp bold) 3:1
UI components 3:1
Focus indicators 3:1

Touch Target Sizes

// Minimum touch target: 48dp x 48dp
IconButton(
    onClick = { /* action */ },
    modifier = Modifier.size(48.dp) // Meets accessibility minimum
) {
    Icon(
        Icons.Rounded.Add,
        modifier = Modifier.size(24.dp) // Icon can be smaller
    )
}

Font Scaling

Always use sp for text sizes to respect user preferences:

// ✅ Respects user font size preferences
Text(fontSize = 16.sp)

// ❌ Ignores user preferences
Text(fontSize = 16.dp) // DON'T DO THIS

Additional Components

7. Vertical Floating Toolbar

For side-docked or vertical layouts:

VerticalFloatingToolbar(
    expanded = isExpanded,
    modifier = Modifier
        .align(Alignment.CenterEnd)
        .systemBarsPadding()
        .padding(end = 16.dp)
) {
    IconButton(onClick = { /* action */ }) {
        Icon(Icons.Rounded.Edit, "Edit")
    }
    IconButton(onClick = { /* action */ }) {
        Icon(Icons.Rounded.Share, "Share")
    }
    IconButton(onClick = { /* action */ }) {
        Icon(Icons.Rounded.Delete, "Delete")
    }
}

8. Expressive Progress Indicators

Updated with thicker, wavy designs:

// Linear - now thicker and wavy
LinearProgressIndicator(
    modifier = Modifier
        .fillMaxWidth()
        .height(8.dp) // Thicker than before
)

// Circular - enhanced styling
CircularProgressIndicator(
    modifier = Modifier.size(48.dp),
    strokeWidth = 4.dp
)

// NEW: Loading Indicator for short waits
LoadingIndicator(
    modifier = Modifier.size(48.dp)
    // Morphs through 7 different shapes!
)

9. Search Bar + Search View

Modern search with expressive transitions:

var searchQuery by remember { mutableStateOf("") }
var isExpanded by remember { mutableStateOf(false) }

SearchBar(
    inputField = {
        SearchBarDefaults.InputField(
            query = searchQuery,
            onQueryChange = { searchQuery = it },
            onSearch = { /* handle search */ },
            expanded = isExpanded,
            onExpandedChange = { isExpanded = it },
            placeholder = { Text("Search songs...") },
            leadingIcon = { Icon(Icons.Rounded.Search, null) },
            trailingIcon = {
                if (searchQuery.isNotEmpty()) {
                    IconButton(onClick = { searchQuery = "" }) {
                        Icon(Icons.Rounded.Close, "Clear")
                    }
                }
            }
        )
    },
    expanded = isExpanded,
    onExpandedChange = { isExpanded = it }
) {
    // Search suggestions/results here
}

Micro-Interactions That Delight

Small details that create a premium feel:

Shimmer Loading Effect

@Composable
fun ShimmerCard() {
    val shimmer = rememberInfiniteTransition()
    val alpha by shimmer.animateFloat(
        initialValue = 0.3f,
        targetValue = 0.7f,
        animationSpec = infiniteRepeatable(
            animation = tween(1000),
            repeatMode = RepeatMode.Reverse
        )
    )
    
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(80.dp)
            .clip(RoundedCornerShape(16.dp))
            .background(
                MaterialTheme.colorScheme.surfaceVariant.copy(alpha = alpha)
            )
    )
}

Success Checkmark Animation

var showSuccess by remember { mutableStateOf(false) }

AnimatedVisibility(
    visible = showSuccess,
    enter = scaleIn(
        initialScale = 0.5f,
        animationSpec = spring(Spring.DampingRatioMediumBouncy)
    ) + fadeIn()
) {
    Icon(
        imageVector = Icons.Rounded.CheckCircle,
        tint = Color(0xFF4CAF50),
        modifier = Modifier.size(32.dp)
    )
}

Haptic Feedback

val haptic = LocalHapticFeedback.current

Button(
    onClick = {
        haptic.performHapticFeedback(HapticFeedbackType.LongPress)
        // Your action
    }
) {
    Text("Save")
}

Design Process & Tips from Designers

The Recommended Workflow

1. 🎯 Define Your Brand Identity

Before touching components, establish:

  • What emotions should your app evoke?
  • What's your brand personality (fun, professional, playful, calm)?
  • What are your brand colors?

2. 🎨 Use the Material Theme Builder

Generate a complete color scheme from your brand color:

3. 📐 Set Up Your Design System in Figma

Use the official Material 3 Design Kit:

  • Customize colors, typography, shapes
  • Create component variants for your brand
  • Document your decisions

4. 🧪 Start Small, Test Often

"Begin with one screen or component, then expand."

  • Don't try to redesign everything at once
  • Implement expressive tactics one at a time
  • Test with real users early

5. 📱 Test on Real Devices

  • Spring animations can feel different on various devices
  • Test dynamic color on devices with different wallpapers
  • Verify motion respects "Reduce motion" settings

Tips from Real App Redesigns

From the "Now in Android" Case Study:

"We explored brand identity through the Material Theme Builder plugin. The colors needed to maintain personality even when dynamic color adapted them to user wallpapers."

Key Insight: Your brand should shine through regardless of dynamic color choices.

From a Productivity App Redesign:

"Users described our Material 2 design as 'functional but forgettable.' Material 3 transformed it into something personal and engaging."

Key Insight: The design system enables expression—but you have to choose to be expressive.

From a Non-Profit App (Wilber):

"We used Material 3's 26+ color roles to create clear hierarchy. Every component was thoroughly tested to ensure consistent visual hierarchy."

Key Insight: Color roles exist for a reason—use them purposefully.


Case Studies & Inspiration

1. Now in Android

What they did well:

  • Bold, vibrant brand colors
  • Clear visual hierarchy through color roles
  • Consistent component customization
  • Design file publicly available

Link: Search "Now in Android Material 3 case study" on Medium

2. Backdrops App

What makes it special:

  • One of the first Material 3 Expressive redesigns
  • Delightful animations throughout
  • Interface feels "alive and responsive"
  • Great example of shape morphing in action

3. Google Play Store

What to learn:

  • Carousel implementation
  • Card hierarchy and depth
  • Dynamic color integration
  • Search bar design

4. Gmail

What to learn:

  • Floating toolbar implementation
  • FAB design
  • List interactions
  • Navigation patterns

Inspiration Sources

Source What You'll Find
Dribbble Visual inspiration, concept designs
Material.io Official guidelines, component specs
Medium Case studies, design process articles
Android Dev Blog Implementation details, new features
YouTube Tutorials, Google I/O sessions

Implementation Guide

Getting Started with Compose Material 3

// Required dependency (use alpha for Expressive features)
implementation("androidx.compose.material3:material3:1.4.0-alpha14")

// For graphics-shapes (custom shapes)
implementation("androidx.graphics:graphics-shapes:1.0.0")

Setting Up Your Theme

@Composable
fun IvorMusicTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context)
            else dynamicLightColorScheme(context)
        }
        darkTheme -> darkColorScheme()
        else -> lightColorScheme()
    }
    
    MaterialTheme(
        colorScheme = colorScheme,
        typography = AppTypography,
        shapes = AppShapes,
        content = content
    )
}

Premium Press Effect

@Composable
fun PressableCard(
    onClick: () -> Unit,
    content: @Composable () -> Unit
) {
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed by interactionSource.collectIsPressedAsState()
    
    val scale by animateFloatAsState(
        targetValue = if (isPressed) 0.97f else 1f,
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    )
    
    Box(
        modifier = Modifier
            .scale(scale)
            .clip(RoundedCornerShape(16.dp))
            .clickable(
                interactionSource = interactionSource,
                indication = ripple()
            ) { onClick() }
    ) {
        content()
    }
}

Staggered List Animation

@Composable
fun AnimatedList(items: List<Item>) {
    LazyColumn {
        itemsIndexed(items) { index, item ->
            var visible by remember { mutableStateOf(false) }
            
            LaunchedEffect(Unit) {
                delay(index * 50L) // 50ms stagger
                visible = true
            }
            
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(300)) + 
                        slideInVertically(
                            initialOffsetY = { it / 3 },
                            animationSpec = spring(
                                dampingRatio = Spring.DampingRatioMediumBouncy
                            )
                        )
            ) {
                ItemCard(item)
            }
        }
    }
}

Premium Design Checklist

✅ Must-Haves

  • Spring animations on all interactive elements
  • Consistent corner radii (pick 2-3 sizes)
  • Generous whitespace (16-24dp padding)
  • High-quality images (use high-res where available)
  • Pull-to-refresh on content screens
  • Ripple effects on all clickable elements
  • Clear visual hierarchy (size, color, spacing)
  • Accessibility (respects system font size, reduce motion)

✅ Nice-to-Haves

  • Shape morphing on buttons
  • Staggered list animations
  • Loading skeletons (not spinners)
  • Success animations (checkmarks, etc.)
  • Dynamic color support
  • Custom shapes for brand identity
  • Emphasized typography for key text

❌ Avoid

  • Flat buttons without interaction feedback
  • Abrupt state changes without transitions
  • Generic icons (use Rounded/Filled variants)
  • Crowded, cluttered layouts
  • Inconsistent spacing
  • Snap/instant animations for user-facing actions
  • Ignoring reduced motion preferences
  • Using spinners for short loading times

Resources & Links

📚 Official Documentation

Resource URL Description
Material Design 3 https://m3.material.io/ Official guidelines
M3 Expressive https://material.io/blog/material-3-expressive Overview blog post
Compose Material 3 https://developer.android.com/develop/ui/compose/designsystems/material3 Android implementation
Motion Guidelines https://m3.material.io/styles/motion Animation specs
Shape Guidelines https://m3.material.io/styles/shape Shape system
Color Guidelines https://m3.material.io/styles/color Color roles
Typography https://m3.material.io/styles/typography Type scale

🛠️ Design Tools

Tool URL What It Does
Theme Builder https://m3.material.io/theme-builder Generate color schemes
Figma M3 Kit https://www.figma.com/community/file/1035203688168086460 Design components
Material Symbols https://fonts.google.com/icons Icon library

📺 Video Resources

Channel/Source Content
Material Design YouTube Official tutorials
Google I/O Sessions Annual design updates
Android Developers Implementation guides
Philipp Lackner Compose tutorials
Stevdza-San UI/Compose examples

📖 Articles & Case Studies

Topic Where to Find
Now in Android Case Study Medium
M3 App Redesign Stories Medium, Dev.to
Compose Samples Android Developer docs
Community Examples GitHub

🎨 Inspiration

Source URL
Dribbble https://dribbble.com/tags/material3
Mobbin https://mobbin.com/browse/android
Awwwards https://www.awwwards.com/websites/mobile/

Final Thoughts

"Good design is obvious. Great design is transparent."
— Joe Sparano

Material 3 Expressive gives you the tools to create truly exceptional apps. But tools are just tools—the magic comes from:

  1. Understanding your users and their emotional needs
  2. Making intentional choices about every design decision
  3. Testing and iterating based on real feedback
  4. Caring about the details that users feel but might not articulate

The best Material 3 apps don't just implement the guidelines—they use them as a foundation to express something unique. Your app should feel like you made it, not like Google made it.


Happy Designing! 🎨✨

This guide is a living document. Update it as Material Design evolves and as you learn new techniques.