feat: adapter le thème Material3 à la palette visuelle Bonsai

Remplace les couleurs dynamiques Android 12+ et le schéma Material3
par défaut par la palette extraite du webapp Bonsai (bleu #2563eb,
fond #f9fafb, surface blanche, contours gris). Ajoute la typographie
complète (13 styles) et renomme les libellés "Planify" en "BonsaiTask".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 09:04:45 +02:00
parent 1dcfb0f525
commit b08ceb5574
4 changed files with 173 additions and 21 deletions
@@ -81,14 +81,14 @@ fun MainScreen(viewModel: DrawerViewModel = hiltViewModel()) {
)
val title = drawerTitles[currentRoute]
?: projects.find { "project/${it.id}" == currentRoute }?.name
?: "Planify"
?: "BonsaiTask"
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet {
Text(
text = "Planify",
text = "BonsaiTask",
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 20.dp),
)
@@ -1,21 +1,104 @@
package com.planify.mobile.ui.theme
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.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.graphics.Color
import androidx.hilt.navigation.compose.hiltViewModel
import com.planify.mobile.data.preferences.ThemeMode
private val LightColorScheme = lightColorScheme()
private val DarkColorScheme = darkColorScheme()
// Bonsai design tokens — extracted from the webapp CSS palette
private val Blue600 = Color(0xFF2563EB)
private val Blue700 = Color(0xFF1D4ED8)
private val Blue800 = Color(0xFF1E3A8A)
private val Blue100 = Color(0xFFDBEAFE)
private val Blue50 = Color(0xFFEFF6FF)
private val Blue300 = Color(0xFF93C5FD)
private val Blue400 = Color(0xFF60A5FA)
private val Gray50 = Color(0xFFF9FAFB)
private val Gray100 = Color(0xFFF3F4F6)
private val Gray200 = Color(0xFFE5E7EB)
private val Gray300 = Color(0xFFD1D5DB)
private val Gray400 = Color(0xFF9CA3AF)
private val Gray500 = Color(0xFF6B7280)
private val Gray600 = Color(0xFF4B5563)
private val Gray700 = Color(0xFF374151)
private val Gray800 = Color(0xFF1F2937)
private val Gray900 = Color(0xFF111827)
private val Green800 = Color(0xFF276749)
private val Green600 = Color(0xFF2F855A)
private val Green200 = Color(0xFFD1FAE5)
private val Green900 = Color(0xFF14532D)
private val Red600 = Color(0xFFDC2626)
private val Red100 = Color(0xFFFEE2E2)
private val Red900 = Color(0xFF7F1D1D)
private val BonsaiLightColorScheme = lightColorScheme(
primary = Blue600,
onPrimary = Color.White,
primaryContainer = Blue100,
onPrimaryContainer = Blue800,
secondary = Blue700,
onSecondary = Color.White,
secondaryContainer = Blue50,
onSecondaryContainer = Blue700,
tertiary = Green800,
onTertiary = Color.White,
tertiaryContainer = Green200,
onTertiaryContainer = Green900,
error = Red600,
onError = Color.White,
errorContainer = Red100,
onErrorContainer = Red900,
background = Gray50,
onBackground = Gray900,
surface = Color.White,
onSurface = Gray900,
surfaceVariant = Gray100,
onSurfaceVariant = Gray700,
outline = Gray200,
outlineVariant = Gray300,
inverseSurface = Gray800,
inverseOnSurface = Gray50,
inversePrimary = Blue300,
)
private val BonsaiDarkColorScheme = darkColorScheme(
primary = Blue300,
onPrimary = Blue800,
primaryContainer = Blue700,
onPrimaryContainer = Blue100,
secondary = Blue400,
onSecondary = Blue800,
secondaryContainer = Blue800,
onSecondaryContainer = Blue100,
tertiary = Green200,
onTertiary = Green900,
tertiaryContainer = Green600,
onTertiaryContainer = Green200,
error = Color(0xFFF87171),
onError = Red900,
errorContainer = Color(0xFF991B1B),
onErrorContainer = Color(0xFFFECACA),
background = Gray900,
onBackground = Gray50,
surface = Gray800,
onSurface = Gray50,
surfaceVariant = Gray700,
onSurfaceVariant = Gray300,
outline = Gray600,
outlineVariant = Gray700,
inverseSurface = Gray50,
inverseOnSurface = Gray900,
inversePrimary = Blue600,
)
@Composable
fun PlanifyTheme(
@@ -30,17 +113,8 @@ fun PlanifyTheme(
ThemeMode.SYSTEM -> systemDark
}
val colorScheme = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (isDark) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
isDark -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
colorScheme = if (isDark) BonsaiDarkColorScheme else BonsaiLightColorScheme,
typography = Typography,
content = content,
)
@@ -6,10 +6,88 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
val Typography = Typography(
displayLarge = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 57.sp,
lineHeight = 64.sp,
letterSpacing = (-0.25).sp,
),
displayMedium = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 45.sp,
lineHeight = 52.sp,
),
displaySmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 36.sp,
lineHeight = 44.sp,
),
headlineLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 32.sp,
lineHeight = 40.sp,
),
headlineMedium = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 28.sp,
lineHeight = 36.sp,
),
headlineSmall = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
),
titleLarge = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp,
lineHeight = 28.sp,
),
titleMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp,
),
titleSmall = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp,
),
bodyLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
letterSpacing = 0.5.sp,
),
bodyMedium = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp,
),
bodySmall = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.4.sp,
),
labelLarge = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp,
),
labelMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp,
),
labelSmall = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp,
),
)