agentsclimarketplace

Material3

Skill iammohdzaki/kmp-skills/skills/design-system/material3

Instead of copying and pasting the same prompts into every new project, you install this repo globally into your AI assistant. The AI learns exactly how to structure an AGP 9.0+ project, how to scaffold MVI architecture, how to resolve real library versions, and how to audit your Compose UI for Material 3 compliance.

Install
npx -y skills add iammohdzaki/kmp-skills --skill material3

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Comprehensive Material 3 (Material You) design system skill for Jetpack Compose and Compose Multiplatform (KMP). Covers color tokens, typography, shape, 30+ components, adaptive layout, navigation patterns, dynamic color, dark mode, motion/animation, and accessibility. Compose-first — no web or Flutter code.

SKILL.md

25.6 KB, as published. Nobody here has run it

Material Design 3 — KMP / Compose Multiplatform Skill

This skill guides implementation of Google's Material Design 3 (MD3 / Material You) using Jetpack Compose and Compose Multiplatform for KMP projects (Android + Desktop).

Attribution: This skill is adapted from and gives credit to hamen/material-3-skill by Hamen. The original skill covers web and Flutter targets. This KMP edition strips all web/CSS/Flutter patterns and replaces them with pure Compose Multiplatform APIs, adds the audit report system, and extends the reference set for adaptive layout, navigation, and versioning.

Scope: Compose-only. All examples use androidx.compose.material3 APIs — the same API surface is available in KMP commonMain via org.jetbrains.compose.material3:material3 (declared explicitly in libs.versions.toml). No web CSS, no @material/web elements, no Flutter.


MD3 Philosophy

PrincipleWhat it means in Compose
PersonalDynamic color from user wallpaper (Android 12+). Static fallback for Desktop.
AdaptiveWindowSizeClass drives layout changes across compact → expanded screens.
ExpressiveSpring-based motion, shape morphing, emphasized typography.

Google I/O 2026 Key Updates

  • Compose-first on Android: For all new Android work, use androidx.compose.material3.
  • Expressive layout scaffold: Design screens to adapt across mobile, desktop, foldables. Use Material3Adaptive scaffold APIs.
  • 8dp spacing system: Define spacing as tokens — never scatter raw Dp literals.
  • New expressive components: Lists, menus, search, and search app bars have refreshed expressive guidance; check your Material3 BOM for expressive variants.

Design Token System

All MD3 values come through MaterialTheme. Never hardcode raw values inline.

Token categoryAccess in Compose
ColorMaterialTheme.colorScheme.*
TypographyMaterialTheme.typography.*
ShapeMaterialTheme.shapes.*
SpacingDefine a Dimens object (no built-in API)

Decision Tree

What are you building?

Full app scaffold        → AppTheme setup + references/theming-and-dynamic-color.md
Single component         → references/component-catalog.md
Custom color theme       → references/color-system.md
Typography / fonts       → references/typography-and-shape.md
Navigation structure     → references/navigation-patterns.md
Adaptive layout          → references/layout-and-responsive.md

Color Token Summary

Full details in references/color-system.md.

Key Roles (Compose token → usage)

RoleTokenPrimary Usage
PrimarycolorScheme.primaryFAB, key buttons, active states
On PrimarycolorScheme.onPrimaryText/icons on primary
Primary ContainercolorScheme.primaryContainerTonal buttons, selected chips
On Primary ContainercolorScheme.onPrimaryContainerText on primary container
SecondarycolorScheme.secondaryLess prominent accents, filters
Secondary ContainercolorScheme.secondaryContainerRecessive fills
TertiarycolorScheme.tertiaryContrasting accent sections
SurfacecolorScheme.surfaceCards, sheets, menus
Surface ContainercolorScheme.surfaceContainerNavigation areas
On SurfacecolorScheme.onSurfaceBody text, icons
On Surface VariantcolorScheme.onSurfaceVariantPlaceholder, helper text
OutlinecolorScheme.outlineInput borders, dividers
ErrorcolorScheme.errorError states

Typography Token Summary

Full details in references/typography-and-shape.md.

CategoryStylesUsage
DisplayL / M / SHero text, large numbers
HeadlineL / M / SScreen/section headers
TitleL / M / SToolbar titles, card headers
BodyL / M / SParagraph text, descriptions
LabelL / M / SButtons, chips, captions
// ✅ Always via MaterialTheme
Text("Title", style = MaterialTheme.typography.titleLarge)
Text("Body", style = MaterialTheme.typography.bodyMedium)

// ❌ Never inline
Text("Title", fontSize = 22.sp, fontWeight = FontWeight.Normal)

Shape Token Summary

TokenCorner RadiusTypical Components
shapes.extraSmall4dpChips, snackbars
shapes.small8dpText fields, menus
shapes.medium12dpCards
shapes.large16dpFABs, nav drawer
shapes.extraLarge28dpDialogs, bottom sheets

Elevation

MD3 communicates depth through tonal surface color, not drop shadows.

LevelCompose APITonal OffsetUse
0Elevation.Level0 / 0.dpNoneFlat surfaces at rest
1Elevation.Level1 / 1.dp+5% primaryElevated cards
2Elevation.Level2 / 3.dp+8% primaryMenus, nav bar
3Elevation.Level3 / 6.dp+11% primaryFAB, dialogs
// Cards respect tonal elevation automatically via surfaceTonalElevation
ElevatedCard(elevation = CardDefaults.elevatedCardElevation(defaultElevation = 6.dp)) { }

Motion Summary

Full details in references/typography-and-shape.md §Motion.

EasingComposeUsage
EmphasizedCubicBezierEasing(0.2f, 0f, 0f, 1f)Elements staying on screen
Emphasized DecelerateCubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)Entering screen
Emphasized AccelerateCubicBezierEasing(0.3f, 0f, 0.8f, 0.15f)Leaving screen
StandardFastOutSlowInEasingUtility animations

Standard Durations

TokenDurationUsage
Short100–200msIcon/color state changes
Medium300–400msComponent expand/collapse
Long400–500msScreen-level transitions

Component Quick Reference

ComponentCompose APICategory
Button (Filled)Button {}Actions
Button (Tonal)FilledTonalButton {}Actions
Button (Outlined)OutlinedButton {}Actions
Button (Text)TextButton {}Actions
FABFloatingActionButton {}Actions
Extended FABExtendedFloatingActionButton {}Actions
Icon ButtonIconButton {}, FilledIconButton {}Actions
Segmented ButtonSegmentedButton {}Actions
CardCard {}, ElevatedCard {}, OutlinedCard {}Containment
DialogAlertDialog {}, Dialog {}Containment
Bottom SheetModalBottomSheet {}Sheets
SnackbarSnackbarHost {}Communication
ProgressCircularProgressIndicator(), LinearProgressIndicator()Communication
BadgeBadgedBox {}Communication
CheckboxCheckbox()Input
RadioButtonRadioButton()Input
SwitchSwitch()Input
SliderSlider(), RangeSlider()Input
TextFieldTextField(), OutlinedTextField()Input
ChipsFilterChip, AssistChip, InputChip, SuggestionChipInput
TopAppBarTopAppBar, CenterAlignedTopAppBar, LargeTopAppBarNavigation
Navigation BarNavigationBar {}Navigation
Navigation RailNavigationRail {}Navigation
Navigation DrawerModalNavigationDrawer {}Navigation
TabsTabRow {}, ScrollableTabRow {}Navigation

Full Compose API + examples: references/component-catalog.md


AppTheme Setup (Quick Start)

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is Android 12+ only — always falls back to static on Desktop
    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
    )
}

For Compose Multiplatform Desktop: Remove Build.VERSION_SDK_INT check and always use LightColorScheme / DarkColorScheme. Dynamic color has no JVM equivalent.

Full theming guide: references/theming-and-dynamic-color.md


Core Rules

  • Never hardcode Color(0xFF...) in composables — always MaterialTheme.colorScheme.*
  • Never inline fontSize, fontFamily, fontWeight — always MaterialTheme.typography.*
  • Never inline RoundedCornerShape(12.dp) — always MaterialTheme.shapes.*
  • Always wrap content in AppTheme at the root — never in individual screens
  • Always support dark mode — test every screen with isSystemInDarkTheme()
  • Always use Scaffold — it handles topBar, bottomBar, FAB, snackbarHost, padding
  • Minimum touch target: 48×48dp for all interactive elements
  • Spacing tokens: always multiples of 4dp — define a Dimens object
  • For Desktop/JVM: always use static color schemes — no dynamic color API on JVM

MD3 Compliance Audit

When the user asks for an audit, a compliance check, or passes code / a screen name with the audit argument, run a full MD3 compliance report using the template below.

How to trigger

audit [screen name or paste code here]
audit HomeScreen
audit <paste composable code>
check this screen against material 3
run md3 audit

Audit Process

  1. Scan the target — read the provided code or ask the user to paste the composable(s) to audit.
  2. Check each category below in order.
  3. Output the report using the exact format specified.
  4. Offer fixes — for every ❌ or ⚠️, provide the corrected Compose code snippet inline.

Audit Report Format

Output the report in this exact structure:

╔══════════════════════════════════════════════════════════╗
║          MD3 COMPLIANCE AUDIT — [Screen/File Name]       ║
║          KMP / Compose Multiplatform Edition             ║
╚══════════════════════════════════════════════════════════╝

Score: [X / 10]   Grade: [A / B / C / D / F]

┌─────────────────────────────────────────────────────────┐
│ CATEGORY RESULTS                                        │
└─────────────────────────────────────────────────────────┘

[✅ / ⚠️ / ❌]  COLOR SYSTEM          [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  TYPOGRAPHY            [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  SHAPE                 [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  SPACING               [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  ELEVATION             [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  COMPONENTS            [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  LAYOUT & ADAPTIVE     [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  NAVIGATION            [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  MOTION & ANIMATION    [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  DARK MODE             [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  ACCESSIBILITY         [PASS / WARN / FAIL]
[✅ / ⚠️ / ❌]  THEMING SETUP         [PASS / WARN / FAIL]

┌─────────────────────────────────────────────────────────┐
│ FINDINGS                                                │
└─────────────────────────────────────────────────────────┘

[findings listed per category — see check rules below]

┌─────────────────────────────────────────────────────────┐
│ FIXES                                                   │
└─────────────────────────────────────────────────────────┘

[corrected code snippets for every ❌ and ⚠️]

Audit Check Rules — Per Category

1. COLOR SYSTEM

CheckPass conditionFail condition
No hardcoded colors in composablesMaterialTheme.colorScheme.* usedColor(0xFF…) literal in UI code
No swapped semantic roleserror used for errors onlyerror used for success/warning
Both schemes definedLightColorScheme + DarkColorScheme existOnly one scheme present
Dynamic color has static fallbackif (dynamicColor && SDK >= S) with else branchDynamic color used unconditionally
Extended colors use CompositionLocalLocalExtendedColors patternRaw color passed as parameter
Desktop: no dynamic color APIjvmMain uses static schemedynamicDarkColorScheme() in jvmMain

2. TYPOGRAPHY

CheckPass conditionFail condition
No inline font sizesMaterialTheme.typography.* usedfontSize = 16.sp inline
No inline font weightsMaterialTheme.typography.* usedfontWeight = FontWeight.Bold inline
Custom font loaded via Res.font.*Font(Res.font.*) for KMPHardcoded path or fontFamily literal
All 15 styles defined if custom typographyTypography(displayLarge = …, labelSmall = …)Missing styles in custom Typography
Body text uses bodyLarge/bodyMediumCorrect role applieddisplayLarge on body copy

3. SHAPE

CheckPass conditionFail condition
No inline RoundedCornerShapeMaterialTheme.shapes.* usedRoundedCornerShape(12.dp) inline
Shape token matches componentCards use shapes.medium, FABs use shapes.extraLargeFAB with shapes.small
Custom shapes defined in AppShapesval AppShapes = Shapes(…) in themeShape overrides scattered in UI

4. SPACING

CheckPass conditionFail condition
Spacing uses Dimens objectDimens.md, Dimens.lg, etc.Scattered 16.dp, 24.dp literals
Values are multiples of 4dp4, 8, 12, 16, 24, 32, 48dp15.dp, 7.dp, 11.dp literals
Screen margins consistentDimens.screenHorizontal usedMixed margin values per screen

5. ELEVATION

CheckPass conditionFail condition
Tonal elevation usedtonalElevation / CardDefaults.elevatedCardElevation()Modifier.shadow(8.dp) for depth
Shadow used only for busy backgroundsRare Modifier.shadow with clear reasonShadows on all cards for styling

6. COMPONENTS

CheckPass conditionFail condition
Only one Button (filled) per sectionSingle primary actionMultiple filled buttons per section
FAB in Scaffold.floatingActionButtonScaffold(floatingActionButton = {…})FAB positioned manually with Box
Scaffold used on every screenScaffold {} wraps each screenNo Scaffold, manual layout
AlertDialog for destructive actionsconfirmButton + dismissButton both presentNo dismiss option on destructive dialog
Lists use ListItemListItem(headlineContent = …)Custom Row replacing ListItem
Buttons use correct emphasis hierarchyFilled → Tonal → Elevated → Outlined → TextMultiple filled buttons, no hierarchy

7. LAYOUT & ADAPTIVE

CheckPass conditionFail condition
WindowSizeClass usedcalculateWindowSizeClass() or currentWindowAdaptiveInfo()Fixed-width if (isTablet) hack
No hardcoded breakpointsWindowWidthSizeClass.* enumif (width > 600.dp) check
Canonical layout pattern usedFeed / List-Detail / Supporting PaneNone of the canonical patterns applied
Edge-to-edge enabledenableEdgeToEdge() in ActivityStatus bar not handled
WindowInsets appliedModifier.statusBarsPadding() or ScaffoldContent hidden behind system bars
Adaptive API used for list-detailNavigableListDetailPaneScaffoldManual Row reimplementing list-detail

8. NAVIGATION

CheckPass conditionFail condition
Nav component matches window sizeNavigationBar on compact, NavigationRail on medium, drawer on expandedBottom nav on tablet
Bottom nav has 3–5 itemsDestination count in range2 or 6+ items in NavigationBar
launchSingleTop = truePresent on all nav clicksDuplicate back-stack entries possible
saveState + restoreStatePresent on nav clicksTab scroll position lost
Type-safe routes@Serializable objects/classesString literal routes
NavController not in ViewModelNavigate via UiEffectnavController injected into ViewModel

9. MOTION & ANIMATION

CheckPass conditionFail condition
Easing matches directionEntering: EmphasizedDecelerate, Leaving: EmphasizedAccelerateSymmetric easing for enter/exit
animate*AsState has label =label = "colorAnimation" presentMissing label parameter
Duration ≤ 500ms screen, ≤ 300ms componentWithin limitstween(800ms) on a button
Spring for interactions, tween for transitionsspring() on drag/toggle, tween() on navtween() on swipe gesture

10. DARK MODE

CheckPass conditionFail condition
isSystemInDarkTheme() wired to themedarkTheme = isSystemInDarkTheme()Hard-coded darkTheme = false
Both schemes testedCode has DarkColorScheme definedOnly LightColorScheme present
@Preview(uiMode = UI_MODE_NIGHT_YES) on previewsBoth light and dark previewsOnly light mode previews

11. ACCESSIBILITY

CheckPass conditionFail condition
Touch targets ≥ 48×48dpIcons/buttons have Modifier.size(48.dp) or largerModifier.size(24.dp) as only modifier on clickable
Icon-only buttons have contentDescriptionNon-null descriptioncontentDescription = null on icon button
Contrast ratio ≥ 4.5:1 (normal text)M3 baseline palette usedCustom palette not validated
No color-only state communicationIcon/text also changes stateOnly color changes for selected state
Semantic roles appliedModifier.semantics { role = Role.Button } where neededCustom clickable without role

12. THEMING SETUP

CheckPass conditionFail condition
Single MaterialTheme call at rootAppTheme wraps root composable onlyMaterialTheme called in individual screens
AppTheme has darkTheme + dynamicColor paramsBoth parameters presentTheme has no parameters
AppTypography, AppShapes definedSeparate files in theme/Defaults used (MaterialTheme() with no args)
Desktop uses expect/actual for themerememberColorScheme split across source setsAndroid-only dynamic color call in commonMain

Scoring

ScoreGradeMeaning
10 / 10AFull MD3 compliance — production ready
8–9 / 10BMinor warnings — good with small fixes
6–7 / 10CSeveral violations — needs attention
4–5 / 10DMajor issues — significant rework needed
0–3 / 10FCritical violations — MD3 not followed

Each category scores 1 point: ✅ PASS = 1pt, ⚠️ WARN = 0.5pt, ❌ FAIL = 0pt. Round to nearest 0.5.


Reference Files

FileContents
references/color-system.mdAll 29 color roles, light/dark schemes, dynamic color, custom extensions
references/theming-and-dynamic-color.mdAppTheme setup, dynamic color, KMP (Android+Desktop) theme split
references/typography-and-shape.mdFull 15-style type scale, font setup, shape tokens, elevation, motion
references/component-catalog.mdAll 30+ components with Compose API + code examples
references/layout-and-responsive.mdWindowSizeClass, adaptive scaffolds, canonical layouts, spacing tokens
references/navigation-patterns.mdNavBar, Rail, Drawer, Tabs — when to use each, Compose wiring

Dependencies

⚠️ Deprecation: plugin accessor shorthands

The compose.material3, compose.ui, compose.foundation shorthand accessors previously provided by the Compose Multiplatform Gradle plugin are deprecated as of CMP 1.10.0-beta01.

Old (deprecated)New (explicit libs entry)
implementation(compose.material3)implementation(libs.compose.material3)
implementation(compose.ui)implementation(libs.compose.ui)
implementation(compose.foundation)implementation(libs.compose.foundation)

⚠️ Breaking: material-icons-core is no longer transitive (since CMP 1.8.2)

Starting with CMP 1.8.2, the implicit dependency on material-icons-core was removed. If your project uses Icons.Default.* or any Material icon, add it explicitly.

gradle/libs.versions.toml

[versions]
kotlin               = "2.1.21"
agp                  = "8.10.0"
composeMultiplatform = "1.8.2"   # org.jetbrains.compose plugin version
coroutines           = "1.10.2"
lifecycle            = "2.9.0"

[libraries]
# ✅ Correct module for commonMain
# The CMP plugin maps this → androidx.compose.material3 on Android automatically
compose-material3          = { module = "org.jetbrains.compose.material3:material3",            version.ref = "composeMultiplatform" }
compose-runtime            = { module = "org.jetbrains.compose.runtime:runtime",                version.ref = "composeMultiplatform" }
compose-foundation         = { module = "org.jetbrains.compose.foundation:foundation",          version.ref = "composeMultiplatform" }
compose-ui                 = { module = "org.jetbrains.compose.ui:ui",                          version.ref = "composeMultiplatform" }
# Declare explicitly — no longer a transitive dep since CMP 1.8.2
compose-material-icons-core = { module = "org.jetbrains.compose.material:material-icons-core", version.ref = "composeMultiplatform" }
compose-ui-tooling-preview  = { module = "org.jetbrains.compose.ui:ui-tooling-preview",        version.ref = "composeMultiplatform" }

[plugins]
kotlinMultiplatform  = { id = "org.jetbrains.kotlin.multiplatform",       version.ref = "kotlin" }
androidApplication   = { id = "com.android.application",                  version.ref = "agp" }
composeMultiplatform = { id = "org.jetbrains.compose",                    version.ref = "composeMultiplatform" }
composeCompiler      = { id = "org.jetbrains.kotlin.plugin.compose",      version.ref = "kotlin" }

composeApp/build.gradle.kts

kotlin {
    sourceSets {
        commonMain.dependencies {
            // ✅ Use libs.* — NOT the deprecated compose.* plugin accessors
            implementation(libs.compose.runtime)
            implementation(libs.compose.foundation)
            implementation(libs.compose.ui)
            implementation(libs.compose.material3)
            implementation(libs.compose.material.icons.core)  // explicit since CMP 1.8.2
        }
        androidMain.dependencies {
            implementation(libs.compose.ui.tooling.preview)
        }
    }
}

Module mapping (how it works)

Source setModule in tomlWhat Gradle actually resolves
commonMainorg.jetbrains.compose.material3:material3JetBrains multiplatform artifact
androidMain (via CMP plugin metadata)same toml entryandroidx.compose.material3:material3
jvmMain (Desktop)same toml entryJetBrains desktop artifact

You never need to manually switch to androidx.compose.material3 in build files — the CMP Gradle plugin metadata handles the platform mapping transparently.


Official Docs

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.