refactor: consolidate theme usage across components, screens, and wheel flow

This commit is contained in:
null 2026-06-16 18:44:23 -05:00
parent 71441bec14
commit 99ff77a357
22 changed files with 197 additions and 161 deletions

View File

@ -122,12 +122,12 @@ private fun AnswerHistoryContent(
Text(
text = "What you have opened",
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = "Private answers and revealed reflections, gathered in one place.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -179,7 +179,7 @@ private fun AnswerHistoryCard(
Text(
text = answer.questionText,
style = MaterialTheme.typography.titleMedium,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
fontWeight = FontWeight.SemiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
@ -187,7 +187,7 @@ private fun AnswerHistoryCard(
Text(
text = if (answer.isRevealed) answer.revealSummary() else "Saved privately. Tap to reveal.",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
@ -198,7 +198,7 @@ private fun AnswerHistoryCard(
Text(
text = if (answer.isRevealed) "Opened" else "Private",
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF6B4A86),
color = Color(0xFF56306F),
fontWeight = FontWeight.SemiBold
)
TextButton(onClick = onDelete) {
@ -216,13 +216,13 @@ private fun AnswerHistoryCard(
private fun HistoryPill(label: String) {
Surface(
shape = RoundedCornerShape(999.dp),
color = Color(0xFFF8F4F1)
color = Color(0xFFFFF8FC)
) {
Text(
text = label,
modifier = Modifier.padding(horizontal = 11.dp, vertical = 7.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF3E3734)
color = Color(0xFF261D2E)
)
}
}

View File

@ -97,7 +97,7 @@ private fun AnswerRevealContent(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(14.dp)
) {
CircularProgressIndicator(color = Color(0xFF8F5FC8))
CircularProgressIndicator(color = Color(0xFFB98AF4))
Text("Loading reveal")
}
}
@ -105,7 +105,7 @@ private fun AnswerRevealContent(
Text(
text = state.error,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
state.answer == null -> NoAnswerState(
@ -330,13 +330,13 @@ private fun AnswerPreview(
private fun RevealPill(label: String) {
Surface(
shape = RoundedCornerShape(999.dp),
color = Color(0xFFF8F4F1)
color = Color(0xFFFFF8FC)
) {
Text(
text = label,
modifier = Modifier.padding(horizontal = 11.dp, vertical = 7.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF3E3734)
color = Color(0xFF261D2E)
)
}
}

View File

@ -38,12 +38,12 @@ fun EmptyState(
text = title,
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = body,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
if (actionLabel != null && onAction != null) {
Button(

View File

@ -27,7 +27,7 @@ fun ErrorState(
Card(
modifier = modifier.fillMaxWidth(),
shape = RoundedCornerShape(28.dp),
colors = CardDefaults.cardColors(containerColor = Color(0xFFFFF4F2))
colors = CardDefaults.cardColors(containerColor = Color(0xFFFFEEF7))
) {
Column(
modifier = Modifier.padding(22.dp),
@ -37,12 +37,12 @@ fun ErrorState(
text = title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF8B2E1A)
color = Color(0xFF8D2D35)
)
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF5C1E0E)
color = Color(0xFF5A5060)
)
if (onRetry != null) {
OutlinedButton(

View File

@ -37,12 +37,12 @@ fun LoadingState(
) {
CircularProgressIndicator(
modifier = Modifier.size(34.dp),
color = Color(0xFF8F5FC8)
color = Color(0xFFB98AF4)
)
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
textAlign = TextAlign.Center
)
}

View File

@ -196,13 +196,13 @@ private fun PlaceholderHeader(
style = MaterialTheme.typography.displaySmall.copy(
fontWeight = FontWeight.SemiBold
),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = description,
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -229,7 +229,7 @@ private fun SignalChip(
text = label,
modifier = Modifier.padding(horizontal = 13.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF3E3734),
color = Color(0xFF261D2E),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)

View File

@ -29,7 +29,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
private val Purple = Color(0xFF5F3A87)
private val Purple = Color(0xFF56306F)
private val PurpleLight = Color(0xFFF0EDF9)
private val PinkPill = Color(0xFFB98AF4)
@ -56,7 +56,7 @@ fun SpecialDatesSection(
Text(
text = "Your Special Dates",
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
if (compact) {
DateCountPill()
@ -87,7 +87,7 @@ fun SpecialDatesSection(
Text(
text = "Your Anniversary",
style = MaterialTheme.typography.bodyLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
if (!compact) {
TodayPill()
@ -96,7 +96,7 @@ fun SpecialDatesSection(
Text(
text = "Added by Jessica",
style = MaterialTheme.typography.bodySmall,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
@ -113,7 +113,7 @@ fun SpecialDatesSection(
Text(
text = "Next up: Jessica's birthday May 10, Mark's birthday Aug 25",
style = MaterialTheme.typography.bodySmall,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
@ -138,7 +138,7 @@ private fun BirthdayRow(name: String, day: String, month: String) {
Text(
text = "$name's Birthday",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
modifier = Modifier.weight(1f)
)

View File

@ -157,7 +157,7 @@ private fun HomeHeader(
Text(
text = "For tonight",
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
modifier = Modifier.weight(1f)
)
if (streakCount > 0) {
@ -170,7 +170,7 @@ private fun HomeHeader(
else
"Open the app, see what matters, and take one small step toward closeness.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -473,29 +473,29 @@ private fun HomeActionTone.actionColors(): HomeActionColors =
deep = Color(0xFF6D2B55)
)
HomeActionTone.Reflection -> HomeActionColors(
soft = Color(0xFFF0E8FF),
accent = Color(0xFFA98FE8),
deep = Color(0xFF4B3279)
soft = Color(0xFFF6E8FF),
accent = Color(0xFFC89AF2),
deep = Color(0xFF56306F)
)
HomeActionTone.Ritual -> HomeActionColors(
soft = Color(0xFFEAF6F0),
accent = Color(0xFF9BC9AE),
deep = Color(0xFF28533A)
soft = Color(0xFFF4E8FF),
accent = Color(0xFFE7A2D1),
deep = Color(0xFF6D2B55)
)
HomeActionTone.Starter -> HomeActionColors(
soft = Color(0xFFFFF0E6),
accent = Color(0xFFEFC39D),
deep = Color(0xFF673D20)
soft = Color(0xFFFFE8F4),
accent = Color(0xFFE7A2D1),
deep = Color(0xFF6D2B55)
)
HomeActionTone.Pack -> HomeActionColors(
soft = Color(0xFFEAF0FF),
accent = Color(0xFF99AEE8),
deep = Color(0xFF2D407A)
soft = Color(0xFFFFE8F4),
accent = Color(0xFFE7A2D1),
deep = Color(0xFF6D2B55)
)
HomeActionTone.Utility -> HomeActionColors(
soft = Color(0xFFF0EDF3),
accent = Color(0xFFB7AFC0),
deep = Color(0xFF423849)
soft = Color(0xFFF4E8FF),
accent = Color(0xFFB98AF4),
deep = Color(0xFF56306F)
)
}
@ -565,7 +565,7 @@ private fun CategoryMiniCard(
Text(
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
style = MaterialTheme.typography.titleSmall,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
fontWeight = FontWeight.SemiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
@ -573,7 +573,7 @@ private fun CategoryMiniCard(
Text(
text = "${item.questionCount} prompts",
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -591,11 +591,11 @@ private fun LoadingHomeCard() {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(14.dp)
) {
CircularProgressIndicator(color = Color(0xFF8F5FC8))
CircularProgressIndicator(color = Color(0xFFB98AF4))
Text(
text = "Opening your dashboard",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -618,13 +618,13 @@ private fun ErrorHomeCard(
Text(
text = "Home paused",
style = MaterialTheme.typography.titleMedium,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
fontWeight = FontWeight.SemiBold
)
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
Button(
onClick = onRefresh,
@ -644,13 +644,13 @@ private fun ErrorHomeCard(
private fun HomePill(label: String) {
Surface(
shape = RoundedCornerShape(999.dp),
color = Color(0xFFF8F4F1)
color = Color(0xFFFFF8FC)
) {
Text(
text = label,
modifier = Modifier.padding(horizontal = 11.dp, vertical = 7.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF3E3734),
color = Color(0xFF261D2E),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)

View File

@ -1,5 +1,6 @@
package com.couplesconnect.app.ui.onboarding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@ -29,6 +30,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
@ -37,6 +39,12 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.couplesconnect.app.core.navigation.AppRoute
import com.couplesconnect.app.ui.auth.AuthBackgroundBrush
import com.couplesconnect.app.ui.auth.AuthInk
import com.couplesconnect.app.ui.auth.AuthMuted
import com.couplesconnect.app.ui.auth.AuthOnPrimary
import com.couplesconnect.app.ui.auth.AuthPrimary
import com.couplesconnect.app.ui.auth.authTextFieldColors
@Composable
fun CreateProfileScreen(
@ -54,7 +62,11 @@ fun CreateProfileScreen(
state.error?.let { snackbar.showSnackbar(it); viewModel.dismissError() }
}
Scaffold(snackbarHost = { SnackbarHost(snackbar) }) { padding ->
Scaffold(
snackbarHost = { SnackbarHost(snackbar) },
containerColor = Color.Transparent,
modifier = Modifier.background(AuthBackgroundBrush)
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
@ -71,14 +83,14 @@ fun CreateProfileScreen(
Text(
text = "What should your\npartner call you?",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.primary,
color = AuthInk,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(8.dp))
Text(
text = "This is how you'll appear to them in the app.",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f),
color = AuthMuted,
textAlign = TextAlign.Center
)
@ -90,6 +102,7 @@ fun CreateProfileScreen(
label = { Text("Your name") },
singleLine = true,
modifier = Modifier.fillMaxWidth(),
colors = authTextFieldColors(),
isError = state.nameError != null,
supportingText = state.nameError?.let { { Text(it, color = MaterialTheme.colorScheme.error) } },
keyboardOptions = KeyboardOptions(
@ -106,9 +119,12 @@ fun CreateProfileScreen(
onClick = { focusManager.clearFocus(); viewModel.saveProfile() },
enabled = !state.isLoading,
modifier = Modifier.fillMaxWidth().height(56.dp),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
colors = ButtonDefaults.buttonColors(
containerColor = AuthPrimary,
contentColor = AuthOnPrimary
)
) {
if (state.isLoading) CircularProgressIndicator(color = MaterialTheme.colorScheme.onPrimary, strokeWidth = 2.dp)
if (state.isLoading) CircularProgressIndicator(color = AuthOnPrimary, strokeWidth = 2.dp)
else Text("Continue", style = MaterialTheme.typography.labelLarge)
}

View File

@ -23,13 +23,16 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.couplesconnect.app.core.navigation.AppRoute
import com.couplesconnect.app.ui.auth.AuthBackgroundBrush
import com.couplesconnect.app.ui.auth.AuthInk
import com.couplesconnect.app.ui.auth.AuthMuted
import com.couplesconnect.app.ui.auth.AuthOnPrimary
import com.couplesconnect.app.ui.auth.AuthPrimary
import com.couplesconnect.app.ui.auth.AuthPrimaryDeep
@Composable
fun OnboardingScreen(
@ -48,20 +51,14 @@ fun OnboardingScreen(
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.linearGradient(
colors = listOf(Color(0xFFFFFBFE), Color(0xFFF8F1FF), Color(0xFFFFEEF7)),
start = Offset.Zero,
end = Offset.Infinite
)
)
.background(AuthBackgroundBrush)
) {
if (state.isCheckingAuth) {
CircularProgressIndicator(
modifier = Modifier
.size(36.dp)
.align(Alignment.Center),
color = MaterialTheme.colorScheme.primary,
color = AuthPrimary,
strokeWidth = 3.dp
)
} else {
@ -80,20 +77,20 @@ fun OnboardingScreen(
Text(
text = "",
style = MaterialTheme.typography.displayLarge,
color = MaterialTheme.colorScheme.primary
color = AuthPrimaryDeep
)
Spacer(Modifier.height(24.dp))
Text(
text = "Closer",
style = MaterialTheme.typography.displayMedium,
color = MaterialTheme.colorScheme.primary,
color = AuthInk,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(12.dp))
Text(
text = "Questions that bring you closer,\none answer at a time.",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f),
color = AuthMuted,
textAlign = TextAlign.Center
)
}
@ -105,7 +102,10 @@ fun OnboardingScreen(
Button(
onClick = { onNavigate(AppRoute.SIGN_UP) },
modifier = Modifier.fillMaxWidth().height(56.dp),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
colors = ButtonDefaults.buttonColors(
containerColor = AuthPrimary,
contentColor = AuthOnPrimary
)
) {
Text("Get started", style = MaterialTheme.typography.labelLarge)
}
@ -114,7 +114,7 @@ fun OnboardingScreen(
Text(
"I already have an account",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f)
color = AuthPrimaryDeep
)
}
}

View File

@ -78,13 +78,13 @@ fun PaywallScreen(
Text(
text = "Go deeper together",
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
textAlign = TextAlign.Center
)
Text(
text = "One subscription. Every question pack we've built for couples — and everything we build next.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
textAlign = TextAlign.Center
)
}
@ -102,7 +102,7 @@ fun PaywallScreen(
Text(
text = "What's included",
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
BENEFITS.forEach { benefit ->
Row(
@ -112,13 +112,13 @@ fun PaywallScreen(
Icon(
imageVector = Icons.Default.Check,
contentDescription = null,
tint = Color(0xFF5F3A87),
tint = Color(0xFF56306F),
modifier = Modifier.size(18.dp)
)
Text(
text = benefit,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF3E3734)
color = Color(0xFF261D2E)
)
}
}
@ -165,7 +165,7 @@ fun PaywallScreen(
TextButton(onClick = { onNavigate("back") }) {
Text(
text = "Not now",
color = Color(0xFF9E9693)
color = Color(0xFF9B8AA6)
)
}
@ -174,13 +174,13 @@ fun PaywallScreen(
modifier = Modifier.fillMaxWidth()
) {
TextButton(onClick = { uriHandler.openUri(ExternalLinks.PRIVACY_POLICY) }) {
Text("Privacy", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9E9693))
Text("Privacy", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9B8AA6))
}
TextButton(onClick = { uriHandler.openUri(ExternalLinks.TERMS_OF_SERVICE) }) {
Text("Terms", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9E9693))
Text("Terms", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9B8AA6))
}
TextButton(onClick = { uriHandler.openUri(ExternalLinks.SUBSCRIPTION_TERMS) }) {
Text("Subscription terms", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9E9693))
Text("Subscription terms", style = MaterialTheme.typography.labelSmall, color = Color(0xFF9B8AA6))
}
}
}

View File

@ -185,12 +185,12 @@ private fun LocalQuestionHeader(
Text(
text = title,
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = subtitle,
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -219,7 +219,7 @@ private fun MetaPill(label: String) {
text = label,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF3E3734),
color = Color(0xFF261D2E),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)

View File

@ -164,7 +164,7 @@ private fun CategoryHero(
Text(
text = title,
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
@ -172,7 +172,7 @@ private fun CategoryHero(
text = category?.description
?: "Browse prompts for this kind of conversation.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
Row(
modifier = Modifier
@ -203,7 +203,7 @@ private fun CategoryFilters(
Text(
text = "Format",
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
fontWeight = FontWeight.SemiBold
)
Row(
@ -249,7 +249,7 @@ private fun FilterPill(
text = label,
modifier = Modifier.padding(horizontal = 13.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelMedium,
color = if (selected) Color(0xFF5F3A87) else Color(0xFF3E3734),
color = if (selected) Color(0xFF56306F) else Color(0xFF261D2E),
fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Medium,
maxLines = 1
)
@ -268,7 +268,7 @@ private fun DepthHeader(depth: Int, count: Int) {
Text(
text = "Depth $depth",
style = MaterialTheme.typography.titleMedium,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
fontWeight = FontWeight.SemiBold
)
CategoryPill("$count ${if (count == 1) "prompt" else "prompts"}")
@ -295,7 +295,7 @@ private fun QuestionListCard(
text = question.text,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
@ -318,13 +318,13 @@ private fun CategoryPill(
) {
Surface(
shape = RoundedCornerShape(999.dp),
color = if (emphasis) Color(0xFFF3E8FF) else Color(0xFFF8F4F1)
color = if (emphasis) Color(0xFFF3E8FF) else Color(0xFFFFF8FC)
) {
Text(
text = label,
modifier = Modifier.padding(horizontal = 11.dp, vertical = 7.dp),
style = MaterialTheme.typography.labelMedium,
color = if (emphasis) Color(0xFF5F3A87) else Color(0xFF3E3734),
color = if (emphasis) Color(0xFF56306F) else Color(0xFF261D2E),
maxLines = 1
)
}
@ -342,11 +342,11 @@ private fun CategoryLoadingCard() {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(14.dp)
) {
CircularProgressIndicator(color = Color(0xFF8F5FC8))
CircularProgressIndicator(color = Color(0xFFB98AF4))
Text(
text = "Loading prompts",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -367,12 +367,12 @@ private fun CategoryMessageCard(title: String, message: String) {
text = title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}

View File

@ -110,12 +110,12 @@ private fun QuestionPackLibraryContent(
Text(
text = "Pick a doorway",
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = "Choose a question pack by the kind of conversation you want to open together.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -190,7 +190,7 @@ private fun QuestionPackCard(
onClick: () -> Unit
) {
val containerColor = if (item.isLocked)
Color(0xFFFAF7F5).copy(alpha = 0.9f)
Color(0xFFFFF8FC).copy(alpha = 0.9f)
else
Color.White.copy(alpha = 0.9f)
val accent = packAccent(item.category.id)
@ -207,7 +207,7 @@ private fun QuestionPackCard(
modifier = Modifier
.fillMaxWidth()
.height(5.dp)
.background(if (item.isLocked) Color(0xFFD9D1CE) else accent)
.background(if (item.isLocked) Color(0xFFE3D4EB) else accent)
)
Column(
modifier = Modifier
@ -227,7 +227,7 @@ private fun QuestionPackCard(
Text(
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
style = MaterialTheme.typography.titleLarge,
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
@ -235,7 +235,7 @@ private fun QuestionPackCard(
Text(
text = item.category.description,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
@ -295,7 +295,7 @@ private fun FilterPill(
text = label,
modifier = Modifier.padding(horizontal = 13.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelMedium,
color = if (selected) Color(0xFF5F3A87) else Color(0xFF3E3734),
color = if (selected) Color(0xFF56306F) else Color(0xFF261D2E),
fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Medium,
maxLines = 1
)
@ -309,13 +309,13 @@ private fun PackPill(
) {
Surface(
shape = RoundedCornerShape(999.dp),
color = if (emphasis) Color(0xFFF3E8FF) else Color(0xFFF8F4F1)
color = if (emphasis) Color(0xFFF3E8FF) else Color(0xFFFFF8FC)
) {
Text(
text = label,
modifier = Modifier.padding(horizontal = 11.dp, vertical = 7.dp),
style = MaterialTheme.typography.labelMedium,
color = if (emphasis) Color(0xFF5F3A87) else Color(0xFF3E3734),
color = if (emphasis) Color(0xFF56306F) else Color(0xFF261D2E),
maxLines = 1
)
}
@ -339,11 +339,11 @@ private fun QuestionPackItem.metadataLabels(): List<String> {
private fun packAccent(categoryId: String): Color {
val palette = listOf(
Color(0xFF5F3A87),
Color(0xFF5C7C8A),
Color(0xFF6F7D4F),
Color(0xFF8A5A74),
Color(0xFF7A6A3A)
Color(0xFF56306F),
Color(0xFF8A4BC1),
Color(0xFFB98AF4),
Color(0xFFB65F93),
Color(0xFFE7A2D1)
)
return palette[kotlin.math.abs(categoryId.hashCode()) % palette.size]
}
@ -360,11 +360,11 @@ private fun LoadingPackCard() {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(14.dp)
) {
CircularProgressIndicator(color = Color(0xFF8F5FC8))
CircularProgressIndicator(color = Color(0xFFB98AF4))
Text(
text = "Loading question packs",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -385,12 +385,12 @@ private fun PackMessageCard(title: String, message: String) {
text = title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}

View File

@ -3,7 +3,7 @@ package com.couplesconnect.app.ui.theme
import androidx.compose.ui.graphics.Color
// Dark theme colors (for reference if needed)
val darkPrimaryColor = Color(0xFF8F5FC8)
val darkPrimaryColor = Color(0xFFB98AF4)
val darkPrimaryContainerColor = Color(0xFF43255F)
val darkSecondaryColor = Color(0xFFFFAFD9)
val darkTertiaryColor = Color(0xFFB98AF4)

View File

@ -22,13 +22,16 @@ fun CouplesConnectTheme(
}
// Purple-pink color palette (Light theme)
val PrimaryColor = Color(0xFF8F5FC8)
val PrimaryColor = Color(0xFFB98AF4)
val PrimaryContainerColor = Color(0xFFF3E8FF)
val SecondaryColor = Color(0xFFE7A2D1)
val TertiaryColor = Color(0xFFB98AF4)
val BackgroundColor = Color(0xFFFFFBFE)
val SurfaceColor = Color(0xFFFFFBFE)
val ErrorColor = Color(0xFF8D2D35)
val SurfaceVariantColor = Color(0xFFF4E8FF)
val OutlineColor = Color(0xFF9B8AA6)
val OutlineVariantColor = Color(0xFFE3D4EB)
val OnPrimaryColor = Color(0xFF24122F)
val OnPrimaryContainerColor = Color(0xFF321545)
@ -36,6 +39,7 @@ val OnSecondaryColor = Color(0xFF2E1731)
val OnTertiaryColor = Color(0xFF24122F)
val OnBackgroundColor = Color(0xFF261D2E)
val OnSurfaceColor = Color(0xFF261D2E)
val OnSurfaceVariantColor = Color(0xFF5A5060)
val OnErrorColor = Color(0xFFFFFFFF)
val lightColors = lightColorScheme(
@ -45,12 +49,20 @@ val lightColors = lightColorScheme(
onPrimaryContainer = OnPrimaryContainerColor,
secondary = SecondaryColor,
onSecondary = OnSecondaryColor,
secondaryContainer = Color(0xFFFFE8F4),
onSecondaryContainer = Color(0xFF3B1730),
tertiary = TertiaryColor,
onTertiary = OnTertiaryColor,
tertiaryContainer = Color(0xFFF4E8FF),
onTertiaryContainer = Color(0xFF321545),
background = BackgroundColor,
surface = SurfaceColor,
onBackground = OnBackgroundColor,
onSurface = OnSurfaceColor,
surfaceVariant = SurfaceVariantColor,
onSurfaceVariant = OnSurfaceVariantColor,
outline = OutlineColor,
outlineVariant = OutlineVariantColor,
error = ErrorColor,
onError = OnErrorColor
)
@ -62,12 +74,20 @@ val darkColors = darkColorScheme(
onPrimaryContainer = Color(0xFFF3E8FF),
secondary = Color(0xFFFFAFD9),
onSecondary = Color(0xFF3B1730),
secondaryContainer = Color(0xFF5B2847),
onSecondaryContainer = Color(0xFFFFD8EB),
tertiary = Color(0xFFB98AF4),
onTertiary = Color(0xFF24122F),
tertiaryContainer = Color(0xFF43255F),
onTertiaryContainer = Color(0xFFF3E8FF),
background = Color(0xFF18111E),
surface = Color(0xFF211729),
onBackground = Color(0xFFF2E8F6),
onSurface = Color(0xFFF2E8F6),
surfaceVariant = Color(0xFF372641),
onSurfaceVariant = Color(0xFFD9C8E2),
outline = Color(0xFFA996B4),
outlineVariant = Color(0xFF5A4666),
error = Color(0xFFFFB3BA),
onError = OnErrorColor
)

View File

@ -61,55 +61,55 @@ val Typography = Typography(
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
letterSpacing = 0.sp
),
titleSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
letterSpacing = 0.sp
),
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
letterSpacing = 0.sp
),
bodyMedium = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
letterSpacing = 0.sp
),
bodySmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.4.sp
letterSpacing = 0.sp
),
labelLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
letterSpacing = 0.sp
),
labelMedium = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
letterSpacing = 0.sp
)
)

View File

@ -90,12 +90,12 @@ private fun CategoryPickerContent(
Text(
text = "Choose the weather",
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = "Pick a category that matches where you are tonight. The wheel picks the question.",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}
@ -107,8 +107,8 @@ private fun CategoryPickerContent(
horizontalArrangement = Arrangement.spacedBy(14.dp),
verticalAlignment = Alignment.CenterVertically
) {
CircularProgressIndicator(color = Color(0xFF5F3A87))
Text("Loading categories…", style = MaterialTheme.typography.bodyMedium, color = Color(0xFF4E4642))
CircularProgressIndicator(color = Color(0xFF56306F))
Text("Loading categories…", style = MaterialTheme.typography.bodyMedium, color = Color(0xFF5A5060))
}
}
state.error != null -> item {
@ -118,8 +118,8 @@ private fun CategoryPickerContent(
colors = CardDefaults.cardColors(containerColor = Color.White.copy(alpha = 0.84f))
) {
Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
Text("Categories unavailable", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold, color = Color(0xFF27211F))
Text(state.error, style = MaterialTheme.typography.bodyMedium, color = Color(0xFF4E4642))
Text("Categories unavailable", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold, color = Color(0xFF261D2E))
Text(state.error, style = MaterialTheme.typography.bodyMedium, color = Color(0xFF5A5060))
}
}
}
@ -138,7 +138,7 @@ private fun CategoryCard(
item: CategoryPickerItem,
onClick: () -> Unit
) {
val containerColor = if (item.isLocked) Color(0xFFF5F0EC).copy(alpha = 0.84f) else Color.White.copy(alpha = 0.86f)
val containerColor = if (item.isLocked) Color(0xFFFFF8FC).copy(alpha = 0.84f) else Color.White.copy(alpha = 0.86f)
Card(
onClick = onClick,
@ -160,7 +160,7 @@ private fun CategoryCard(
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = if (item.isLocked) Color(0xFF9E9693) else Color(0xFF27211F),
color = if (item.isLocked) Color(0xFF9B8AA6) else Color(0xFF261D2E),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
@ -173,7 +173,7 @@ private fun CategoryCard(
Icon(
imageVector = Icons.Default.Lock,
contentDescription = "Locked",
tint = Color(0xFFB0A9A6),
tint = Color(0xFF9B8AA6),
modifier = Modifier.size(20.dp)
)
}
@ -188,7 +188,7 @@ private fun CategoryPill(label: String) {
text = label,
modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp),
style = MaterialTheme.typography.labelSmall,
color = Color(0xFF4A3F7A)
color = Color(0xFF56306F)
)
}
}

View File

@ -109,7 +109,7 @@ private fun SpinWheelContent(
Text(
text = "Let the prompt find you",
style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
textAlign = TextAlign.Center
)
if (state.categoryName.isNotBlank()) {
@ -121,7 +121,7 @@ private fun SpinWheelContent(
text = state.categoryName,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelLarge,
color = Color(0xFF4A3F7A)
color = Color(0xFF56306F)
)
}
}
@ -143,7 +143,7 @@ private fun SpinWheelContent(
Text(
text = if (state.spunAndReady) "" else "",
fontSize = 64.sp,
color = if (state.spunAndReady) Color(0xFFB98AF4) else Color(0xFF5F3A87)
color = if (state.spunAndReady) Color(0xFFB98AF4) else Color(0xFF56306F)
)
}
}
@ -157,7 +157,7 @@ private fun SpinWheelContent(
state.error != null -> Text(
text = state.error,
style = MaterialTheme.typography.bodySmall,
color = Color(0xFFB5473A),
color = Color(0xFF8D2D35),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
@ -165,7 +165,7 @@ private fun SpinWheelContent(
Text(
text = "${SpinWheelViewModel.SESSION_SIZE} questions selected",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
@ -173,7 +173,7 @@ private fun SpinWheelContent(
onClick = onStart,
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5F3A87))
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF56306F))
) {
Text("Start session", color = Color.White)
}
@ -185,12 +185,12 @@ private fun SpinWheelContent(
Text("Spin again")
}
}
state.isLoading -> CircularProgressIndicator(color = Color(0xFF5F3A87))
state.isLoading -> CircularProgressIndicator(color = Color(0xFF56306F))
else -> {
Text(
text = "Tap to select ${SpinWheelViewModel.SESSION_SIZE} questions at random",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
@ -198,7 +198,7 @@ private fun SpinWheelContent(
onClick = onSpin,
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5F3A87))
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF56306F))
) {
Text("Spin", color = Color.White)
}

View File

@ -131,14 +131,14 @@ private fun WheelCompleteContent(
Text(
text = "Session complete",
style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
textAlign = TextAlign.Center
)
if (categoryName.isNotBlank()) {
Text(
text = categoryName,
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642),
color = Color(0xFF5A5060),
textAlign = TextAlign.Center
)
}
@ -164,7 +164,7 @@ private fun WheelCompleteContent(
Text(
text = "of $total questions",
style = MaterialTheme.typography.bodyLarge,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}

View File

@ -94,7 +94,7 @@ fun WheelHistoryScreen(
Text(
text = "Spin sessions",
style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
modifier = Modifier.padding(top = 20.dp, bottom = 4.dp)
)
}
@ -145,12 +145,12 @@ private fun WheelSessionCard(session: QuestionSession) {
text = session.categoryId.displayCategoryName(),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = "${session.questionIds.size} questions",
style = MaterialTheme.typography.bodySmall,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
session.completedAt?.let { ts ->
@ -192,12 +192,12 @@ private fun WheelHistoryLockedCard(onUnlock: () -> Unit) {
text = "History is a premium feature",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
text = "Unlock to browse all your past spin wheel sessions together.",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
Button(
onClick = onUnlock,

View File

@ -106,22 +106,22 @@ private fun WheelSessionContent(
text = state.categoryName,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
style = MaterialTheme.typography.labelMedium,
color = Color(0xFF4A3F7A)
color = Color(0xFF56306F)
)
}
}
Text(
text = "${current + 1} / $total",
style = MaterialTheme.typography.labelLarge,
color = Color(0xFF9E9693)
color = Color(0xFF9B8AA6)
)
}
LinearProgressIndicator(
progress = { progress },
modifier = Modifier.fillMaxWidth(),
color = Color(0xFF5F3A87),
trackColor = Color(0xFFE8E4F0)
color = Color(0xFF56306F),
trackColor = Color(0xFFF4E8FF)
)
val question = state.questions.getOrNull(current)
@ -143,7 +143,7 @@ private fun WheelSessionContent(
Text(
text = question?.text ?: "",
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.SemiBold),
color = Color(0xFF27211F),
color = Color(0xFF261D2E),
textAlign = TextAlign.Center,
lineHeight = MaterialTheme.typography.titleLarge.lineHeight
)
@ -158,7 +158,7 @@ private fun WheelSessionContent(
onClick = onNext,
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5F3A87))
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF56306F))
) {
Text(
text = if (current + 1 >= total) "Finish" else "Next question",
@ -180,7 +180,7 @@ private fun WheelSessionContent(
onClick = onEnd,
modifier = Modifier.weight(1f)
) {
Text("End session", color = Color(0xFF9E9693))
Text("End session", color = Color(0xFF9B8AA6))
}
}
}
@ -203,12 +203,12 @@ private fun EmptySessionCard() {
"No active session",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
color = Color(0xFF261D2E)
)
Text(
"Go back to the category picker and spin the wheel to start.",
style = MaterialTheme.typography.bodyMedium,
color = Color(0xFF4E4642)
color = Color(0xFF5A5060)
)
}
}