← All courses

Theming & Dark Mode

🗓 May 31, 2026 ⏱ 2 min read

How theming works in Compose

MaterialTheme provides three things to everything inside it: a color scheme, typography, and shapes. Components read from these automatically, so changing the theme restyles your whole app consistently.

Defining colors

private val LightColors = lightColorScheme(
    primary = Color(0xFF7C3AED),
    secondary = Color(0xFFA855F7),
    background = Color(0xFFFAF8FF)
)

private val DarkColors = darkColorScheme(
    primary = Color(0xFFC4B5FD),
    background = Color(0xFF12101A)
)

A theme wrapper with dark mode

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),   // follows the device
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) DarkColors else LightColors
    MaterialTheme(
        colorScheme = colors,
        typography = Typography(),
        content = content
    )
}

isSystemInDarkTheme() automatically returns true when the user has dark mode on, so your app switches with the system.

Using theme values (never hard-code)

Text(
    "Title",
    color = MaterialTheme.colorScheme.primary,
    style = MaterialTheme.typography.titleLarge
)

Surface(color = MaterialTheme.colorScheme.surface) { /* ... */ }

Because you reference colorScheme rather than fixed colors, the same code looks correct in both light and dark mode.

Typography and shapes

val typography = Typography(
    titleLarge = TextStyle(fontSize = 22.sp, fontWeight = FontWeight.Bold),
    bodyMedium = TextStyle(fontSize = 15.sp)
)

Dynamic color (Android 12+)

On Android 12+, you can derive your color scheme from the user’s wallpaper with dynamicLightColorScheme(context) for a personalised look.

Common mistakes

  • Hard-coding Color.White/Color.Black — broken in dark mode. Use theme colors.
  • Forgetting to wrap the app in your AppTheme.
  • Mixing raw hex colors throughout the UI instead of centralising them.
Summary: Wrap your app in a MaterialTheme with light/dark color schemes, read colors and fonts from MaterialTheme, and use isSystemInDarkTheme() so dark mode works automatically.