From 697d778db778a4abed0fa10541e44034e3e231ef Mon Sep 17 00:00:00 2001 From: Han Yin Date: Fri, 11 Apr 2025 14:35:16 -0700 Subject: [PATCH] UI: define theme, color palette, typography and shape --- .../example/llama/revamp/ui/theme/Color.kt | 70 ++++++++++ .../example/llama/revamp/ui/theme/Shape.kt | 16 +++ .../example/llama/revamp/ui/theme/Theme.kt | 122 +++++++++++++++++ .../com/example/llama/revamp/ui/theme/Type.kt | 125 ++++++++++++++++++ 4 files changed, 333 insertions(+) create mode 100644 examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Color.kt create mode 100644 examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Shape.kt create mode 100644 examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Theme.kt create mode 100644 examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Type.kt diff --git a/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Color.kt b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Color.kt new file mode 100644 index 0000000000..8e6ccef4eb --- /dev/null +++ b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Color.kt @@ -0,0 +1,70 @@ +package com.example.llama.revamp.ui.theme + + +import androidx.compose.ui.graphics.Color + +// Light Theme Colors +val md_theme_light_primary = Color(0xFF4527A0) +val md_theme_light_onPrimary = Color(0xFFFFFFFF) +val md_theme_light_primaryContainer = Color(0xFFE8DDFF) +val md_theme_light_onPrimaryContainer = Color(0xFF22005D) +val md_theme_light_secondary = Color(0xFF625B71) +val md_theme_light_onSecondary = Color(0xFFFFFFFF) +val md_theme_light_secondaryContainer = Color(0xFFE8DEF8) +val md_theme_light_onSecondaryContainer = Color(0xFF1E192B) +val md_theme_light_tertiary = Color(0xFF7D5260) +val md_theme_light_onTertiary = Color(0xFFFFFFFF) +val md_theme_light_tertiaryContainer = Color(0xFFFFD9E3) +val md_theme_light_onTertiaryContainer = Color(0xFF31101D) +val md_theme_light_error = Color(0xFFBA1A1A) +val md_theme_light_errorContainer = Color(0xFFFFDAD6) +val md_theme_light_onError = Color(0xFFFFFFFF) +val md_theme_light_onErrorContainer = Color(0xFF410002) +val md_theme_light_background = Color(0xFFFFFBFF) +val md_theme_light_onBackground = Color(0xFF1C1B1E) +val md_theme_light_surface = Color(0xFFFFFBFF) +val md_theme_light_onSurface = Color(0xFF1C1B1E) +val md_theme_light_surfaceVariant = Color(0xFFE7E0EB) +val md_theme_light_onSurfaceVariant = Color(0xFF49454E) +val md_theme_light_outline = Color(0xFF7A757F) +val md_theme_light_inverseOnSurface = Color(0xFFF4EFF4) +val md_theme_light_inverseSurface = Color(0xFF313033) +val md_theme_light_inversePrimary = Color(0xFFCFBCFF) +val md_theme_light_surfaceTint = Color(0xFF6750A4) +val md_theme_light_outlineVariant = Color(0xFFCAC4CF) +val md_theme_light_scrim = Color(0xFF000000) + +// Dark Theme Colors +val md_theme_dark_primary = Color(0xFFCFBCFF) +val md_theme_dark_onPrimary = Color(0xFF381E72) +val md_theme_dark_primaryContainer = Color(0xFF4F378A) +val md_theme_dark_onPrimaryContainer = Color(0xFFE8DDFF) +val md_theme_dark_secondary = Color(0xFFCBC2DB) +val md_theme_dark_onSecondary = Color(0xFF332D41) +val md_theme_dark_secondaryContainer = Color(0xFF4A4458) +val md_theme_dark_onSecondaryContainer = Color(0xFFE8DEF8) +val md_theme_dark_tertiary = Color(0xFFEFB8C8) +val md_theme_dark_onTertiary = Color(0xFF4A2532) +val md_theme_dark_tertiaryContainer = Color(0xFF633B48) +val md_theme_dark_onTertiaryContainer = Color(0xFFFFD9E3) +val md_theme_dark_error = Color(0xFFFFB4AB) +val md_theme_dark_errorContainer = Color(0xFF93000A) +val md_theme_dark_onError = Color(0xFF690005) +val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) +val md_theme_dark_background = Color(0xFF1C1B1E) +val md_theme_dark_onBackground = Color(0xFFE6E1E6) +val md_theme_dark_surface = Color(0xFF1C1B1E) +val md_theme_dark_onSurface = Color(0xFFE6E1E6) +val md_theme_dark_surfaceVariant = Color(0xFF49454E) +val md_theme_dark_onSurfaceVariant = Color(0xFFCAC4CF) +val md_theme_dark_outline = Color(0xFF948F99) +val md_theme_dark_inverseOnSurface = Color(0xFF1C1B1E) +val md_theme_dark_inverseSurface = Color(0xFFE6E1E6) +val md_theme_dark_inversePrimary = Color(0xFF6750A4) +val md_theme_dark_surfaceTint = Color(0xFFCFBCFF) +val md_theme_dark_outlineVariant = Color(0xFF49454E) +val md_theme_dark_scrim = Color(0xFF000000) + +// Additional app-specific colors +val WarningColor = Color(0xFFFFA000) +val SuccessColor = Color(0xFF388E3C) diff --git a/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Shape.kt b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Shape.kt new file mode 100644 index 0000000000..a7e443556a --- /dev/null +++ b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Shape.kt @@ -0,0 +1,16 @@ +package com.example.llama.revamp.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.ui.unit.dp + +val Shapes = Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(8.dp), + large = RoundedCornerShape(16.dp) +) + +// Additional custom shapes for specific components +val CardShape = RoundedCornerShape(12.dp) +val ButtonShape = RoundedCornerShape(8.dp) +val InputFieldShape = RoundedCornerShape(8.dp) diff --git a/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Theme.kt b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Theme.kt new file mode 100644 index 0000000000..ae6113e337 --- /dev/null +++ b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Theme.kt @@ -0,0 +1,122 @@ +package com.example.llama.revamp.ui.theme + + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat +import com.google.accompanist.systemuicontroller.rememberSystemUiController + +private val LightColorScheme = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, +) + +private val DarkColorScheme = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, +) + +@Composable +fun LlamaTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = false, + 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 + } + + val view = LocalView.current + if (!view.isInEditMode) { + val systemUiController = rememberSystemUiController() + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.background.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme + + // Set status bar and navigation bar colors + systemUiController.setSystemBarsColor( + color = colorScheme.background, + darkIcons = !darkTheme + ) + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + shapes = Shapes, + content = content + ) +} diff --git a/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Type.kt b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Type.kt new file mode 100644 index 0000000000..86c0656655 --- /dev/null +++ b/examples/llama.android/app/src/main/java/com/example/llama/revamp/ui/theme/Type.kt @@ -0,0 +1,125 @@ +package com.example.llama.revamp.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 + +// Set of Material typography styles to start with +val Typography = Typography( + displayLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 57.sp, + lineHeight = 64.sp, + letterSpacing = (-0.25).sp + ), + displayMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 45.sp, + lineHeight = 52.sp, + letterSpacing = 0.sp + ), + displaySmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 36.sp, + lineHeight = 44.sp, + letterSpacing = 0.sp + ), + headlineLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing = 0.sp + ), + headlineMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 28.sp, + lineHeight = 36.sp, + letterSpacing = 0.sp + ), + headlineSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp + ), + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + titleMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.15.sp + ), + titleSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp + ), + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + bodyMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.25.sp + ), + bodySmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.4.sp + ), + labelLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp + ), + labelMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) +) + +// Additional specific text styles +val MonospacedTextStyle = TextStyle( + fontFamily = FontFamily.Monospace, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.sp +)