From 3b1d9965742a5028aa23c9221b8762a6915b74c8 Mon Sep 17 00:00:00 2001 From: Avinal Kumar Date: Tue, 19 May 2026 17:09:37 +0530 Subject: [PATCH] Add Windows Phone Metro theme system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Color system: - Dark (#1F1F1F bg), Light (white bg), AMOLED (pure black bg) - All 20 WP8 accent colors (Lime through Taupe) - User-selectable accent color persisted in DataStore - Default: Cobalt (#0050EF) Typography (WP scale): - 54sp Light for page titles, 32sp Light for pivot headers - 24sp Light for section headers, 17sp body, 15sp normal, 14sp small - SemiBold for emphasis, Light for large display text Flat surfaces only — no elevation, no tonal surfaces, no Material chrome. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Avinal Kumar --- .../kotlin/com/avinal/memos/ui/theme/Color.kt | 101 ++++++++++++++++++ .../kotlin/com/avinal/memos/ui/theme/Theme.kt | 27 +++++ .../kotlin/com/avinal/memos/ui/theme/Type.kt | 24 +++++ 3 files changed, 152 insertions(+) create mode 100644 composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Color.kt create mode 100644 composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Theme.kt create mode 100644 composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Type.kt diff --git a/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Color.kt b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Color.kt new file mode 100644 index 0000000..36c5697 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Color.kt @@ -0,0 +1,101 @@ +package com.avinal.memos.ui.theme + +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.ui.graphics.Color + +val PriorityP1 = Color(0xFFE51400) +val PriorityP2 = Color(0xFFF0A30A) +val PriorityP3 = Color(0xFF1BA1E2) +val LabelGreen = Color(0xFF60A917) +val DuePurple = Color(0xFF6A00FF) +val OverdueRed = Color(0xFFE51400) + +// --- WP8 Accent Colors --- +data class AccentColor(val name: String, val color: Color) + +val WpAccentColors = listOf( + AccentColor("Lime", Color(0xFFA4C400)), + AccentColor("Green", Color(0xFF60A917)), + AccentColor("Emerald", Color(0xFF008A00)), + AccentColor("Teal", Color(0xFF00ABA9)), + AccentColor("Cyan", Color(0xFF1BA1E2)), + AccentColor("Cobalt", Color(0xFF0050EF)), + AccentColor("Indigo", Color(0xFF6A00FF)), + AccentColor("Violet", Color(0xFFAA00FF)), + AccentColor("Pink", Color(0xFFF472D0)), + AccentColor("Magenta", Color(0xFFD80073)), + AccentColor("Crimson", Color(0xFFA20025)), + AccentColor("Red", Color(0xFFE51400)), + AccentColor("Orange", Color(0xFFFA6800)), + AccentColor("Amber", Color(0xFFF0A30A)), + AccentColor("Yellow", Color(0xFFE3C800)), + AccentColor("Brown", Color(0xFF825A2C)), + AccentColor("Olive", Color(0xFF6D8764)), + AccentColor("Steel", Color(0xFF647687)), + AccentColor("Mauve", Color(0xFF76608A)), + AccentColor("Taupe", Color(0xFF87794E)), +) + +val LocalAccentColor = compositionLocalOf { Color(0xFF0050EF) } + +// --- Metro Theme Variants --- +enum class MetroTheme(val label: String) { + DARK("dark"), + LIGHT("light"), + AMOLED("amoled"), +} + +fun metroColorScheme(theme: MetroTheme, accent: Color): ColorScheme = when (theme) { + MetroTheme.DARK -> darkColorScheme( + background = Color(0xFF1F1F1F), + onBackground = Color.White, + surface = Color(0xFF1F1F1F), + onSurface = Color.White, + surfaceVariant = Color(0xFF2A2A2A), + onSurfaceVariant = Color(0xFF999999), + primary = accent, + onPrimary = Color.White, + secondary = Color(0xFF333333), + onSecondary = Color(0xFFCCCCCC), + error = Color(0xFFE51400), + onError = Color.White, + outline = Color(0xFF666666), + outlineVariant = Color(0xFF444444), + ) + MetroTheme.LIGHT -> lightColorScheme( + background = Color.White, + onBackground = Color.Black, + surface = Color.White, + onSurface = Color.Black, + surfaceVariant = Color(0xFFF0F0F0), + onSurfaceVariant = Color(0xFF666666), + primary = accent, + onPrimary = Color.White, + secondary = Color(0xFFE8E8E8), + onSecondary = Color(0xFF333333), + error = Color(0xFFE51400), + onError = Color.White, + outline = Color(0xFFCCCCCC), + outlineVariant = Color(0xFFE0E0E0), + ) + MetroTheme.AMOLED -> darkColorScheme( + background = Color.Black, + onBackground = Color.White, + surface = Color.Black, + onSurface = Color.White, + surfaceVariant = Color(0xFF111111), + onSurfaceVariant = Color(0xFF999999), + primary = accent, + onPrimary = Color.White, + secondary = Color(0xFF1A1A1A), + onSecondary = Color(0xFFCCCCCC), + error = Color(0xFFE51400), + onError = Color.White, + outline = Color(0xFF555555), + outlineVariant = Color(0xFF333333), + ) +} diff --git a/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Theme.kt b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Theme.kt new file mode 100644 index 0000000..d6b0f8f --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Theme.kt @@ -0,0 +1,27 @@ +package com.avinal.memos.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.graphics.Color +import com.avinal.memos.util.LocalAppDependencies + +@Composable +fun MemosAppTheme(content: @Composable () -> Unit) { + val deps = LocalAppDependencies.current + val themeName by deps.tokenStore.theme.collectAsState(initial = "DARK") + val accentName by deps.tokenStore.accentColor.collectAsState(initial = "Cobalt") + + val metroTheme = try { MetroTheme.valueOf(themeName) } catch (_: Exception) { MetroTheme.DARK } + val accent = WpAccentColors.find { it.name == accentName }?.color ?: Color(0xFF0050EF) + + CompositionLocalProvider(LocalAccentColor provides accent) { + MaterialTheme( + colorScheme = metroColorScheme(metroTheme, accent), + typography = MetroTypography, + content = content, + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Type.kt b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Type.kt new file mode 100644 index 0000000..a176a8a --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/avinal/memos/ui/theme/Type.kt @@ -0,0 +1,24 @@ +package com.avinal.memos.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +val MetroTypography = Typography( + displayLarge = TextStyle(fontSize = 54.sp, fontWeight = FontWeight.Light, letterSpacing = (-0.5).sp), + displayMedium = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Light, letterSpacing = 0.sp), + displaySmall = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Light, letterSpacing = 0.sp), + headlineLarge = TextStyle(fontSize = 32.sp, fontWeight = FontWeight.Light, letterSpacing = 0.sp), + headlineMedium = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Light, letterSpacing = 0.sp), + headlineSmall = TextStyle(fontSize = 19.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), + titleLarge = TextStyle(fontSize = 24.sp, fontWeight = FontWeight.Light, letterSpacing = 0.sp), + titleMedium = TextStyle(fontSize = 17.sp, fontWeight = FontWeight.SemiBold, letterSpacing = 0.sp), + titleSmall = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.SemiBold, letterSpacing = 0.sp), + bodyLarge = TextStyle(fontSize = 17.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), + bodyMedium = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), + bodySmall = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), + labelLarge = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.SemiBold, letterSpacing = 0.sp), + labelMedium = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), + labelSmall = TextStyle(fontSize = 12.sp, fontWeight = FontWeight.Normal, letterSpacing = 0.sp), +)