TecMeli implements Material Design 3 theming with support for light/dark modes and dynamic colors on Android 12+.
Overview
The theming system consists of three main components:
Color.kt - Color palette definitions
Theme.kt - Theme composition and color schemes
Type.kt - Typography system
The app automatically adapts to system theme preferences and supports dynamic color extraction on Android 12+.
Color System
Colors are defined following Material Design 3 specifications with separate palettes for light and dark themes.
Color Palette
package com.alcalist.tecmeli.ui.theme
import androidx.compose.ui.graphics.Color
// Dark Theme Colors
val Purple80 = Color ( 0xFFD0BCFF )
val PurpleGrey80 = Color ( 0xFFCCC2DC )
val Pink80 = Color ( 0xFFEFB8C8 )
// Light Theme Colors
val Purple40 = Color ( 0xFF6650a4 )
val PurpleGrey40 = Color ( 0xFF625b71 )
val Pink40 = Color ( 0xFF7D5260 )
Color Roles
Primary Main brand color used for key components
Secondary Accent color for less prominent components
Tertiary Additional accent for complementary elements
Color Breakdown
Color Variable Hex Code Theme Role Purple80#D0BCFFDark Primary PurpleGrey80#CCC2DCDark Secondary Pink80#EFB8C8Dark Tertiary Purple40#6650a4Light Primary PurpleGrey40#625b71Light Secondary Pink40#7D5260Light Tertiary
The “80” suffix indicates high luminance for dark theme, while “40” indicates lower luminance for light theme, following Material Design 3 naming conventions.
Theme Implementation
The main theme composable manages color schemes and applies them throughout the app.
TECMELITheme Composable
@Composable
fun TECMELITheme (
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 = Typography,
content = content
)
}
Color Scheme Definitions
private val DarkColorScheme = darkColorScheme (
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
Theme Parameters
Default : isSystemInDarkTheme()
Determines whether to use dark or light color scheme
Automatically follows system preference
Can be overridden for manual control
Default : true
Enables Material You dynamic color on Android 12+
Extracts colors from wallpaper
Falls back to static colors on older Android versions
content: @Composable () -> Unit
The app content wrapped by the theme
Receives the active color scheme and typography
All child composables inherit theme values
Dynamic Color Support
Android 12+ supports dynamic color extraction from the user’s wallpaper.
How It Works
Check Android Version
Verify device is running Android 12 (S) or higher
Extract Colors
Use dynamicDarkColorScheme() or dynamicLightColorScheme() from Material3
Apply Scheme
MaterialTheme automatically applies the dynamic colors
Fallback
On older devices, use predefined DarkColorScheme or LightColorScheme
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
}
Dynamic color is enabled by default. Set dynamicColor = false to use static colors on all devices.
Typography
The app uses Material Design 3 typography with customizable text styles.
Typography Definition
package com.alcalist.tecmeli.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
val Typography = Typography (
bodyLarge = TextStyle (
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16 .sp,
lineHeight = 24 .sp,
letterSpacing = 0.5 .sp
)
/* Additional text styles:
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
Text Style Properties
Property Value Purpose fontFamilyFontFamily.DefaultUses system default font fontWeightFontWeight.NormalRegular weight for body text fontSize16.spComfortable reading size lineHeight24.spOptimal spacing for readability letterSpacing0.5.spSubtle spacing for clarity
Material3 Typography Scale
Display Styles
displayLarge (57sp)
displayMedium (45sp)
displaySmall (36sp)
Headline Styles
headlineLarge (32sp)
headlineMedium (28sp)
headlineSmall (24sp)
Title Styles
titleLarge (22sp)
titleMedium (16sp)
titleSmall (14sp)
Body Styles
bodyLarge (16sp)
bodyMedium (14sp)
bodySmall (12sp)
Label Styles
labelLarge (14sp)
labelMedium (12sp)
labelSmall (11sp)
Usage Examples
Applying the Theme
import com.alcalist.tecmeli.ui.theme.TECMELITheme
@Composable
fun MyApp () {
TECMELITheme {
// Your app content
NavigationWrapper ()
}
}
Using Theme Colors
@Composable
fun MyComponent () {
Surface (
color = MaterialTheme.colorScheme.primary
) {
Text (
text = "Hello TecMeli" ,
color = MaterialTheme.colorScheme.onPrimary
)
}
}
Accessing Color Scheme
Primary Colors
Surface Colors
Error Colors
val primary = MaterialTheme.colorScheme.primary
val onPrimary = MaterialTheme.colorScheme.onPrimary
val primaryContainer = MaterialTheme.colorScheme.primaryContainer
Using Typography
@Composable
fun TextExample () {
Column {
Text (
text = "Title" ,
style = MaterialTheme.typography.titleLarge
)
Text (
text = "Body text content" ,
style = MaterialTheme.typography.bodyLarge
)
Text (
text = "Small label" ,
style = MaterialTheme.typography.labelSmall
)
}
}
Customization
Adding Custom Colors
// In Color.kt
val CustomBlue = Color ( 0xFF1976D2 )
val CustomGreen = Color ( 0xFF388E3C )
// In Theme.kt
private val LightColorScheme = lightColorScheme (
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40,
background = Color ( 0xFFFFFBFE ),
surface = Color ( 0xFFFFFBFE )
)
Custom Typography
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
val CustomFontFamily = FontFamily (
Font (R.font.custom_regular, FontWeight.Normal),
Font (R.font.custom_bold, FontWeight.Bold)
)
val Typography = Typography (
bodyLarge = TextStyle (
fontFamily = CustomFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16 .sp,
lineHeight = 24 .sp,
letterSpacing = 0.5 .sp
)
)
Disabling Dynamic Color
@Composable
fun MyApp () {
TECMELITheme (
dynamicColor = false // Always use static colors
) {
NavigationWrapper ()
}
}
Theme Components in Use
HomeScreen Example
@Composable
fun HomeScreen () {
Scaffold { paddingValues ->
Column (modifier = Modifier. padding (paddingValues)) {
Text (
text = "Search Results" ,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurface
)
ProductList (products = products)
}
}
}
Error State Example
@Composable
fun ErrorMessage (message: String ) {
Text (
text = message,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.error
)
}
Best Practices
Always use MaterialTheme.colorScheme rather than hardcoded colors: // ✓ Good
color = MaterialTheme.colorScheme.primary
// ✗ Avoid
color = Color ( 0xFF6650a4 )
Apply predefined typography styles for consistency: // ✓ Good
style = MaterialTheme.typography.bodyLarge
// ✗ Avoid
fontSize = 16 .sp, fontWeight = FontWeight.Normal
Allow users to use their preferred theme: // ✓ Good - follows system preference
TECMELITheme {
// content
}
// ✗ Avoid forcing a theme
TECMELITheme (darkTheme = true ) {
// content
}
Always test your UI in both light and dark themes to ensure proper contrast and readability.
Color Contrast Guidelines
Primary Content Minimum 4.5:1 contrast ratio for body text
Large Text Minimum 3:1 contrast ratio for 18sp+ or bold 14sp+
Icons & Graphics Minimum 3:1 contrast ratio for UI components
Error States High contrast for critical information
Screens See theming applied in screens
Navigation Explore navigation patterns
Material Design 3 Official Material Design guidelines