Theming

Light, dark, and system themes powered by Compose Material 3.

The Kotlin template uses Compose Material 3 with custom light/dark color schemes, DataStore-persisted theme choice, optional Material You dynamic color, and edge-to-edge system bars that follow the active theme.

What it provides

SurfaceStatusImplementation
Theme modesIntegratedAppTheme.Light, Dark, and System
PersistenceIntegratedDataStore keys theme_tag and dynamic_color_enabled
Material 3 schemeIntegratedSoarStarterKotlinTheme wraps MaterialTheme
Dynamic colorIntegratedAvailable on Android 12+ when enabled; off by default
System barsIntegratedMainActivity.ApplySystemBarTheme() updates SystemBarStyle

Key files

Theme selection

AppTheme stores three modes:

Light("light")
Dark("dark")
System("system")

ThemeController maps the DataStore theme_tag into StateFlow<AppTheme> and maps dynamic_color_enabled into StateFlow<Boolean>. MainActivity resolves the selected mode against isSystemInDarkTheme(), then passes both values to SoarStarterKotlinTheme.

The drawer and Component gallery reuse ThemeToggle, a segmented Compose control that switches between System, Light, and Dark.

Color system

Color.kt defines:

  • iOS-style accent and semantic colors, including IosTint, IosDestructive, IosGreen, IosIndigo, and IosOrange.
  • Light and dark base colors for background, foreground, muted, border, input, and ring values.
  • ColorScheme extension properties such as groupedBackground, groupedSurface, groupedInput, labelSecondary, separatorSoft, and tint.

Theme.kt builds explicit Material 3 light and dark color schemes from those tokens. If dynamic color is enabled and the device is Android 12 or newer, dynamicLightColorScheme() or dynamicDarkColorScheme() replaces the custom scheme.

Dynamic color is implemented, persisted, and passed into the root theme, but the stored default is false. Turn it on from your own settings UI if you want Material You behavior exposed to users.

Typography

Type.kt customizes the Material 3 typography scale with default Android fonts, semibold/bold headings, and letterSpacing = 0.sp. Use MaterialTheme.typography in screens instead of hardcoding text sizes.

Edge-to-edge

MainActivity calls enableEdgeToEdge() and uses SystemBarStyle.dark() or SystemBarStyle.light() based on the resolved theme. That keeps status and navigation bar icons readable when the user switches theme.

Most screen backgrounds use MaterialTheme.colorScheme.groupedBackground, matching the starter's grouped mobile settings style.

Rebrand checklist

  1. Replace IosTint and related semantic colors in Color.kt.
  2. Adjust light/dark color schemes in Theme.kt.
  3. Change typography in Type.kt if your brand uses a custom font.
  4. Replace launcher assets under res/drawable, res/mipmap-*, and res/mipmap-anydpi.
  5. Update app_name in strings.xml.
  6. Change applicationId, namespace, and any Play/App Links identifiers when making a real product fork.
  7. Revisit LINKING_DOMAIN, assetlinks.json, release signing, Firebase, and RevenueCat after changing the package name.

Verify

  • Theme choice persists after process restart.
  • System mode follows the device dark-mode setting.
  • Dynamic color only changes the scheme on Android 12+ when enabled.
  • Status and navigation bar icons stay readable in light and dark themes.
  • Launcher icons, display name, package name, and App Links all match the rebranded app.

On this page