Modernize Android UI design system to match iOS
- Create comprehensive design system with Theme.kt, Type.kt, and Shape.kt - Update color palette to match iOS (primary #2563EB, accent #8B5CF6) - Implement modern typography scale across all text styles - Add consistent corner radius system (AppRadius) UI Improvements: - HomeScreen: Add personalized greeting, gradient icons, modern stats - TaskCard: Pill-style badges, semantic colors, clean metadata - ResidencesScreen: Gradient circular icons, location indicators - LoginScreen: Gradient button background, modern card styling Design Features: - Gradient backgrounds for visual interest - Semantic color coding for states - Flat design with minimal elevation - Consistent spacing and typography - Material3 shapes throughout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package com.mycrib.android.ui.components.task
|
package com.mycrib.android.ui.components.task
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
@@ -8,8 +10,11 @@ import androidx.compose.material3.*
|
|||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.mycrib.android.ui.theme.AppColors
|
||||||
import com.mycrib.shared.models.TaskDetail
|
import com.mycrib.shared.models.TaskDetail
|
||||||
import com.mycrib.shared.models.TaskCategory
|
import com.mycrib.shared.models.TaskCategory
|
||||||
import com.mycrib.shared.models.TaskPriority
|
import com.mycrib.shared.models.TaskPriority
|
||||||
@@ -32,10 +37,10 @@ fun TaskCard(
|
|||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = MaterialTheme.shapes.large,
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
|
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp),
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceContainerLowest
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@@ -51,54 +56,75 @@ fun TaskCard(
|
|||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
Text(
|
Text(
|
||||||
text = task.title,
|
text = task.title,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
fontWeight = FontWeight.Bold
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
// Pill-style category badge
|
||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.secondaryContainer,
|
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
shape = RoundedCornerShape(8.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = task.category.name,
|
text = task.category.name.uppercase(),
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
color = MaterialTheme.colorScheme.onSecondaryContainer
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.End,
|
horizontalAlignment = Alignment.End,
|
||||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Surface(
|
// Priority badge with semantic colors
|
||||||
color = when (task.priority.name.lowercase()) {
|
val priorityColor = when (task.priority.name.lowercase()) {
|
||||||
"urgent" -> MaterialTheme.colorScheme.error
|
"urgent", "high" -> Color(0xFFEF4444) // Error/Red
|
||||||
"high" -> MaterialTheme.colorScheme.errorContainer
|
"medium" -> Color(0xFFF59E0B) // Warning/Orange
|
||||||
"medium" -> MaterialTheme.colorScheme.primaryContainer
|
else -> Color(0xFF10B981) // Success/Green
|
||||||
else -> MaterialTheme.colorScheme.surfaceVariant
|
}
|
||||||
},
|
Row(
|
||||||
shape = RoundedCornerShape(10.dp)
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
priorityColor.copy(alpha = 0.15f),
|
||||||
|
RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(6.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(priorityColor)
|
||||||
|
)
|
||||||
Text(
|
Text(
|
||||||
text = task.priority.name.uppercase(),
|
text = task.priority.name.uppercase(),
|
||||||
modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp),
|
style = MaterialTheme.typography.labelSmall,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
color = priorityColor
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status badge with semantic colors
|
||||||
if (task.status != null) {
|
if (task.status != null) {
|
||||||
|
val statusColor = when (task.status.name.lowercase()) {
|
||||||
|
"completed" -> AppColors.taskCompleted
|
||||||
|
"in_progress" -> AppColors.taskInProgress
|
||||||
|
"pending" -> Color(0xFFF59E0B)
|
||||||
|
"cancelled" -> AppColors.taskCanceled
|
||||||
|
else -> Color(0xFF9CA3AF)
|
||||||
|
}
|
||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.tertiaryContainer,
|
color = statusColor.copy(alpha = 0.15f),
|
||||||
shape = RoundedCornerShape(10.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = task.status.name.uppercase(),
|
text = task.status.name.replace("_", " ").uppercase(),
|
||||||
modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp),
|
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
color = MaterialTheme.colorScheme.onTertiaryContainer
|
color = statusColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,42 +140,61 @@ fun TaskCard(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
HorizontalDivider()
|
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Metadata pills
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
// Date pill
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.CalendarToday,
|
Icons.Default.CalendarToday,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(16.dp),
|
modifier = Modifier.size(14.dp),
|
||||||
tint = MaterialTheme.colorScheme.primary
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = task.nextScheduledDate ?: task.dueDate ?: "N/A",
|
text = task.nextScheduledDate ?: task.dueDate ?: "N/A",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
fontWeight = FontWeight.SemiBold
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cost pill
|
||||||
task.estimatedCost?.let {
|
task.estimatedCost?.let {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.AttachMoney,
|
Icons.Default.AttachMoney,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(16.dp),
|
modifier = Modifier.size(14.dp),
|
||||||
tint = MaterialTheme.colorScheme.tertiary
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = "$$it",
|
text = "$$it",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
fontWeight = FontWeight.SemiBold,
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
color = MaterialTheme.colorScheme.tertiary
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +327,8 @@ fun CompletionCard(completion: TaskCompletion) {
|
|||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceVariant
|
containerColor = MaterialTheme.colorScheme.surfaceVariant
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
package com.mycrib.android.ui.screens
|
package com.mycrib.android.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.mycrib.android.ui.theme.AppColors
|
||||||
|
import com.mycrib.android.ui.theme.AppRadius
|
||||||
import com.mycrib.android.viewmodel.ResidenceViewModel
|
import com.mycrib.android.viewmodel.ResidenceViewModel
|
||||||
import com.mycrib.shared.network.ApiResult
|
import com.mycrib.shared.network.ApiResult
|
||||||
|
|
||||||
@@ -30,10 +37,17 @@ fun HomeScreen(
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text("myCrib") },
|
title = { Text("myCrib", style = MaterialTheme.typography.headlineSmall) },
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.background
|
||||||
|
),
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = onLogout) {
|
IconButton(onClick = onLogout) {
|
||||||
Icon(Icons.Default.ExitToApp, contentDescription = "Logout")
|
Icon(
|
||||||
|
Icons.Default.ExitToApp,
|
||||||
|
contentDescription = "Logout",
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -42,71 +56,116 @@ fun HomeScreen(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.padding(16.dp),
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(20.dp)
|
||||||
) {
|
) {
|
||||||
|
// Personalized Greeting
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Welcome back",
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Manage your properties",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
// Summary Card
|
// Summary Card
|
||||||
when (summaryState) {
|
when (summaryState) {
|
||||||
is ApiResult.Success -> {
|
is ApiResult.Success -> {
|
||||||
val summary = (summaryState as ApiResult.Success).data
|
val summary = (summaryState as ApiResult.Success).data
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
shape = MaterialTheme.shapes.large,
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = MaterialTheme.colorScheme.primaryContainer
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
)
|
),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp)
|
.padding(20.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Row(
|
||||||
text = "Overview",
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
) {
|
||||||
)
|
// Gradient circular icon
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2563EB),
|
||||||
|
Color(0xFF8B5CF6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Home,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "Overview",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Your property stats",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
) {
|
) {
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
StatItem(
|
||||||
Text(
|
value = "${summary.residences.size}",
|
||||||
text = "${summary.residences.size}",
|
label = "Properties",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
color = Color(0xFF3B82F6)
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
)
|
||||||
)
|
Divider(
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = "Properties",
|
.height(48.dp)
|
||||||
style = MaterialTheme.typography.bodySmall,
|
.width(1.dp),
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
color = MaterialTheme.colorScheme.outlineVariant
|
||||||
)
|
)
|
||||||
}
|
StatItem(
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
value = "${summary.summary.totalTasks}",
|
||||||
Text(
|
label = "Total Tasks",
|
||||||
text = "${summary.summary.totalTasks}",
|
color = Color(0xFF8B5CF6)
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
)
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
Divider(
|
||||||
)
|
modifier = Modifier
|
||||||
Text(
|
.height(48.dp)
|
||||||
text = "Total Tasks",
|
.width(1.dp),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
color = MaterialTheme.colorScheme.outlineVariant
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
)
|
||||||
)
|
StatItem(
|
||||||
}
|
value = "${summary.summary.totalPending}",
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
label = "Pending",
|
||||||
Text(
|
color = Color(0xFFF59E0B)
|
||||||
text = "${summary.summary.totalPending}",
|
)
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "Pending",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = MaterialTheme.colorScheme.onPrimaryContainer
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,66 +190,126 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Residences Card
|
// Residences Card
|
||||||
Card(
|
NavigationCard(
|
||||||
modifier = Modifier
|
title = "Properties",
|
||||||
.fillMaxWidth()
|
subtitle = "Manage your residences",
|
||||||
.clickable { onNavigateToResidences() }
|
icon = Icons.Default.Home,
|
||||||
) {
|
iconColor = Color(0xFF3B82F6),
|
||||||
Row(
|
onClick = onNavigateToResidences
|
||||||
modifier = Modifier
|
)
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Home,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(48.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
Column {
|
|
||||||
Text(
|
|
||||||
text = "Residences",
|
|
||||||
style = MaterialTheme.typography.titleLarge
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "Manage your properties",
|
|
||||||
style = MaterialTheme.typography.bodyMedium
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tasks Card
|
// Tasks Card
|
||||||
Card(
|
NavigationCard(
|
||||||
modifier = Modifier
|
title = "Tasks",
|
||||||
.fillMaxWidth()
|
subtitle = "View and manage tasks",
|
||||||
.clickable { onNavigateToTasks() }
|
icon = Icons.Default.CheckCircle,
|
||||||
) {
|
iconColor = Color(0xFF10B981),
|
||||||
Row(
|
onClick = onNavigateToTasks
|
||||||
modifier = Modifier
|
)
|
||||||
.fillMaxWidth()
|
}
|
||||||
.padding(24.dp),
|
}
|
||||||
verticalAlignment = Alignment.CenterVertically
|
}
|
||||||
) {
|
|
||||||
Icon(
|
@Composable
|
||||||
Icons.Default.CheckCircle,
|
private fun StatItem(
|
||||||
contentDescription = null,
|
value: String,
|
||||||
modifier = Modifier.size(48.dp)
|
label: String,
|
||||||
)
|
color: Color
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
) {
|
||||||
Column {
|
Column(
|
||||||
Text(
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
text = "Tasks",
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
style = MaterialTheme.typography.titleLarge
|
) {
|
||||||
)
|
Box(
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = "View and manage tasks",
|
.size(36.dp)
|
||||||
style = MaterialTheme.typography.bodyMedium
|
.clip(CircleShape)
|
||||||
)
|
.background(color.copy(alpha = 0.1f)),
|
||||||
}
|
contentAlignment = Alignment.Center
|
||||||
}
|
) {
|
||||||
}
|
Text(
|
||||||
|
text = value,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
color = color
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun NavigationCard(
|
||||||
|
title: String,
|
||||||
|
subtitle: String,
|
||||||
|
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||||||
|
iconColor: Color,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onClick() },
|
||||||
|
shape = MaterialTheme.shapes.large,
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
|
),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(20.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
// Gradient circular icon
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(56.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(
|
||||||
|
iconColor,
|
||||||
|
iconColor.copy(alpha = 0.7f)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
icon,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(28.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = subtitle,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
Icons.Default.KeyboardArrowRight,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.mycrib.android.ui.screens
|
|||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
@@ -11,6 +12,8 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
@@ -63,11 +66,11 @@ fun LoginScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(0.9f)
|
.fillMaxWidth(0.9f)
|
||||||
.wrapContentHeight(),
|
.wrapContentHeight(),
|
||||||
shape = RoundedCornerShape(24.dp),
|
shape = MaterialTheme.shapes.extraLarge,
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surface
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
),
|
),
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp)
|
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -123,28 +126,54 @@ fun LoginScreen(
|
|||||||
|
|
||||||
ErrorCard(message = errorMessage)
|
ErrorCard(message = errorMessage)
|
||||||
|
|
||||||
Button(
|
// Gradient button
|
||||||
onClick = {
|
Box(
|
||||||
viewModel.login(username, password)
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(56.dp),
|
.height(56.dp)
|
||||||
enabled = username.isNotEmpty() && password.isNotEmpty(),
|
.clip(MaterialTheme.shapes.medium)
|
||||||
shape = RoundedCornerShape(12.dp)
|
.then(
|
||||||
|
if (username.isNotEmpty() && password.isNotEmpty() && !isLoading) {
|
||||||
|
Modifier.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2563EB),
|
||||||
|
Color(0xFF8B5CF6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Modifier.background(MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.3f))
|
||||||
|
}
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
if (isLoading) {
|
Button(
|
||||||
CircularProgressIndicator(
|
onClick = {
|
||||||
modifier = Modifier.size(24.dp),
|
viewModel.login(username, password)
|
||||||
color = MaterialTheme.colorScheme.onPrimary,
|
},
|
||||||
strokeWidth = 2.dp
|
modifier = Modifier.fillMaxSize(),
|
||||||
)
|
enabled = username.isNotEmpty() && password.isNotEmpty(),
|
||||||
} else {
|
shape = MaterialTheme.shapes.medium,
|
||||||
Text(
|
colors = ButtonDefaults.buttonColors(
|
||||||
"Sign In",
|
containerColor = Color.Transparent,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
disabledContainerColor = Color.Transparent
|
||||||
fontWeight = FontWeight.SemiBold
|
|
||||||
)
|
)
|
||||||
|
) {
|
||||||
|
if (isLoading) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
color = Color.White,
|
||||||
|
strokeWidth = 2.dp
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
"Sign In",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.mycrib.android.ui.screens
|
package com.mycrib.android.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
@@ -11,6 +13,9 @@ import androidx.compose.material3.*
|
|||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
@@ -315,8 +320,11 @@ fun ResidencesScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { onResidenceClick(residence.id) },
|
.clickable { onResidenceClick(residence.id) },
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = MaterialTheme.shapes.large,
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -325,32 +333,67 @@ fun ResidencesScreen(
|
|||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
// Gradient circular house icon
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(56.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2563EB),
|
||||||
|
Color(0xFF8B5CF6)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Home,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(28.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
Text(
|
Text(
|
||||||
text = residence.name,
|
text = residence.name,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
fontWeight = FontWeight.Bold
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Row(
|
||||||
text = "${residence.streetAddress}",
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
) {
|
||||||
)
|
Icon(
|
||||||
Text(
|
Icons.Default.LocationOn,
|
||||||
text = "${residence.city}, ${residence.stateProvince}",
|
contentDescription = null,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
modifier = Modifier.size(14.dp),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = "${residence.city}, ${residence.stateProvince}",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
Icons.Default.KeyboardArrowRight,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
HorizontalDivider()
|
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -360,19 +403,19 @@ fun ResidencesScreen(
|
|||||||
icon = Icons.Default.Assignment,
|
icon = Icons.Default.Assignment,
|
||||||
value = "${residence.taskSummary.total}",
|
value = "${residence.taskSummary.total}",
|
||||||
label = "Tasks",
|
label = "Tasks",
|
||||||
color = MaterialTheme.colorScheme.primary
|
color = Color(0xFF3B82F6)
|
||||||
)
|
)
|
||||||
TaskStatChip(
|
TaskStatChip(
|
||||||
icon = Icons.Default.CheckCircle,
|
icon = Icons.Default.CheckCircle,
|
||||||
value = "${residence.taskSummary.completed}",
|
value = "${residence.taskSummary.completed}",
|
||||||
label = "Done",
|
label = "Done",
|
||||||
color = MaterialTheme.colorScheme.tertiary
|
color = Color(0xFF10B981)
|
||||||
)
|
)
|
||||||
TaskStatChip(
|
TaskStatChip(
|
||||||
icon = Icons.Default.Schedule,
|
icon = Icons.Default.Schedule,
|
||||||
value = "${residence.taskSummary.pending}",
|
value = "${residence.taskSummary.pending}",
|
||||||
label = "Pending",
|
label = "Pending",
|
||||||
color = MaterialTheme.colorScheme.error
|
color = Color(0xFFF59E0B)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.mycrib.android.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Shapes
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
// Modern Shape System - Matching iOS Design System
|
||||||
|
object AppRadius {
|
||||||
|
val xs = 4.dp
|
||||||
|
val sm = 8.dp
|
||||||
|
val md = 12.dp
|
||||||
|
val lg = 16.dp
|
||||||
|
val xl = 20.dp
|
||||||
|
val xxl = 24.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
val AppShapes = Shapes(
|
||||||
|
// Small components (buttons, chips, badges)
|
||||||
|
extraSmall = RoundedCornerShape(AppRadius.xs),
|
||||||
|
small = RoundedCornerShape(AppRadius.sm),
|
||||||
|
|
||||||
|
// Medium components (cards, inputs)
|
||||||
|
medium = RoundedCornerShape(AppRadius.md),
|
||||||
|
|
||||||
|
// Large components (dialogs, sheets)
|
||||||
|
large = RoundedCornerShape(AppRadius.lg),
|
||||||
|
extraLarge = RoundedCornerShape(AppRadius.xl)
|
||||||
|
)
|
||||||
@@ -5,51 +5,73 @@ import androidx.compose.material3.*
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
// Bright color palette
|
// Modern Color Palette - Matching iOS Design System
|
||||||
private val BrightBlue = Color(0xFF007AFF)
|
// Primary Colors - Modern blue gradient
|
||||||
private val BrightGreen = Color(0xFF34C759)
|
private val Primary = Color(0xFF2563EB)
|
||||||
private val BrightOrange = Color(0xFFFF9500)
|
private val PrimaryLight = Color(0xFF3B82F6)
|
||||||
private val BrightRed = Color(0xFFFF3B30)
|
private val PrimaryDark = Color(0xFF1E40AF)
|
||||||
private val BrightPurple = Color(0xFFAF52DE)
|
|
||||||
private val BrightTeal = Color(0xFF5AC8FA)
|
|
||||||
|
|
||||||
// Light variations for containers
|
// Accent Colors
|
||||||
private val LightBlue = Color(0xFFE3F2FD)
|
private val Accent = Color(0xFF8B5CF6)
|
||||||
private val LightGreen = Color(0xFFE8F5E9)
|
private val AccentLight = Color(0xFFA78BFA)
|
||||||
private val LightOrange = Color(0xFFFFF3E0)
|
|
||||||
|
|
||||||
// Dark variations
|
// Semantic Colors
|
||||||
private val DarkBlue = Color(0xFF0A84FF)
|
private val Success = Color(0xFF10B981)
|
||||||
private val DarkGreen = Color(0xFF30D158)
|
private val Warning = Color(0xFFF59E0B)
|
||||||
private val DarkOrange = Color(0xFFFF9F0A)
|
private val Error = Color(0xFFEF4444)
|
||||||
|
private val Info = Color(0xFF3B82F6)
|
||||||
|
|
||||||
|
// Neutral Colors - Modern grays
|
||||||
|
private val Background = Color(0xFFF9FAFB)
|
||||||
|
private val Surface = Color.White
|
||||||
|
private val SurfaceSecondary = Color(0xFFF3F4F6)
|
||||||
|
|
||||||
|
private val TextPrimary = Color(0xFF111827)
|
||||||
|
private val TextSecondary = Color(0xFF6B7280)
|
||||||
|
private val TextTertiary = Color(0xFF9CA3AF)
|
||||||
|
|
||||||
|
private val Border = Color(0xFFE5E7EB)
|
||||||
|
private val BorderLight = Color(0xFFF3F4F6)
|
||||||
|
|
||||||
|
// Task Status Colors
|
||||||
|
private val TaskUpcoming = Color(0xFF3B82F6)
|
||||||
|
private val TaskInProgress = Color(0xFFF59E0B)
|
||||||
|
private val TaskCompleted = Color(0xFF10B981)
|
||||||
|
private val TaskCanceled = Color(0xFF6B7280)
|
||||||
|
private val TaskArchived = Color(0xFF9CA3AF)
|
||||||
|
|
||||||
|
// Dark mode variations
|
||||||
|
private val DarkBackground = Color(0xFF1C1B1F)
|
||||||
|
private val DarkSurface = Color(0xFF2B2930)
|
||||||
|
private val DarkSurfaceSecondary = Color(0xFF3B3842)
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
private val DarkColorScheme = darkColorScheme(
|
||||||
primary = DarkBlue,
|
primary = PrimaryLight,
|
||||||
onPrimary = Color.White,
|
onPrimary = Color.White,
|
||||||
primaryContainer = Color(0xFF003D75),
|
primaryContainer = PrimaryDark,
|
||||||
onPrimaryContainer = Color(0xFFD0E4FF),
|
onPrimaryContainer = Color(0xFFD0E4FF),
|
||||||
|
|
||||||
secondary = DarkGreen,
|
secondary = Success,
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
secondaryContainer = Color(0xFF1B5E20),
|
secondaryContainer = Color(0xFF1B5E20),
|
||||||
onSecondaryContainer = Color(0xFFB9F6CA),
|
onSecondaryContainer = Color(0xFFB9F6CA),
|
||||||
|
|
||||||
tertiary = DarkOrange,
|
tertiary = Warning,
|
||||||
onTertiary = Color.White,
|
onTertiary = Color.White,
|
||||||
tertiaryContainer = Color(0xFF663C00),
|
tertiaryContainer = Color(0xFF663C00),
|
||||||
onTertiaryContainer = Color(0xFFFFE0B2),
|
onTertiaryContainer = Color(0xFFFFE0B2),
|
||||||
|
|
||||||
error = BrightRed,
|
error = Error,
|
||||||
onError = Color.White,
|
onError = Color.White,
|
||||||
errorContainer = Color(0xFF93000A),
|
errorContainer = Color(0xFF93000A),
|
||||||
onErrorContainer = Color(0xFFFFDAD6),
|
onErrorContainer = Color(0xFFFFDAD6),
|
||||||
|
|
||||||
background = Color(0xFF1C1B1F),
|
background = DarkBackground,
|
||||||
onBackground = Color(0xFFE6E1E5),
|
onBackground = Color(0xFFE6E1E5),
|
||||||
|
|
||||||
surface = Color(0xFF1C1B1F),
|
surface = DarkSurface,
|
||||||
onSurface = Color(0xFFE6E1E5),
|
onSurface = Color(0xFFE6E1E5),
|
||||||
surfaceVariant = Color(0xFF49454F),
|
surfaceVariant = DarkSurfaceSecondary,
|
||||||
onSurfaceVariant = Color(0xFFCAC4D0),
|
onSurfaceVariant = Color(0xFFCAC4D0),
|
||||||
|
|
||||||
outline = Color(0xFF938F99),
|
outline = Color(0xFF938F99),
|
||||||
@@ -57,36 +79,36 @@ private val DarkColorScheme = darkColorScheme(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val LightColorScheme = lightColorScheme(
|
private val LightColorScheme = lightColorScheme(
|
||||||
primary = BrightBlue,
|
primary = Primary,
|
||||||
onPrimary = Color.White,
|
onPrimary = Color.White,
|
||||||
primaryContainer = LightBlue,
|
primaryContainer = Color(0xFFEBF2FF),
|
||||||
onPrimaryContainer = Color(0xFF001D35),
|
onPrimaryContainer = PrimaryDark,
|
||||||
|
|
||||||
secondary = BrightGreen,
|
secondary = Success,
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
secondaryContainer = LightGreen,
|
secondaryContainer = Color(0xFFD1FAE5),
|
||||||
onSecondaryContainer = Color(0xFF002106),
|
onSecondaryContainer = Color(0xFF064E3B),
|
||||||
|
|
||||||
tertiary = BrightOrange,
|
tertiary = Warning,
|
||||||
onTertiary = Color.White,
|
onTertiary = Color.White,
|
||||||
tertiaryContainer = LightOrange,
|
tertiaryContainer = Color(0xFFFEF3C7),
|
||||||
onTertiaryContainer = Color(0xFF2B1700),
|
onTertiaryContainer = Color(0xFF78350F),
|
||||||
|
|
||||||
error = BrightRed,
|
error = Error,
|
||||||
onError = Color.White,
|
onError = Color.White,
|
||||||
errorContainer = Color(0xFFFFDAD6),
|
errorContainer = Color(0xFFFEE2E2),
|
||||||
onErrorContainer = Color(0xFF410002),
|
onErrorContainer = Color(0xFF7F1D1D),
|
||||||
|
|
||||||
background = Color(0xFFFFFBFE),
|
background = Background,
|
||||||
onBackground = Color(0xFF1C1B1F),
|
onBackground = TextPrimary,
|
||||||
|
|
||||||
surface = Color(0xFFFFFBFE),
|
surface = Surface,
|
||||||
onSurface = Color(0xFF1C1B1F),
|
onSurface = TextPrimary,
|
||||||
surfaceVariant = Color(0xFFE7E0EC),
|
surfaceVariant = SurfaceSecondary,
|
||||||
onSurfaceVariant = Color(0xFF49454F),
|
onSurfaceVariant = TextSecondary,
|
||||||
|
|
||||||
outline = Color(0xFF79747E),
|
outline = Border,
|
||||||
outlineVariant = Color(0xFFCAC4D0)
|
outlineVariant = BorderLight
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -98,6 +120,20 @@ fun MyCribTheme(
|
|||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
|
typography = AppTypography,
|
||||||
|
shapes = AppShapes,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extended colors for semantic states (not part of Material3 ColorScheme)
|
||||||
|
object AppColors {
|
||||||
|
val accent = Accent
|
||||||
|
val accentLight = AccentLight
|
||||||
|
val info = Info
|
||||||
|
val taskUpcoming = TaskUpcoming
|
||||||
|
val taskInProgress = TaskInProgress
|
||||||
|
val taskCompleted = TaskCompleted
|
||||||
|
val taskCanceled = TaskCanceled
|
||||||
|
val taskArchived = TaskArchived
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package com.mycrib.android.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
|
||||||
|
|
||||||
|
// Modern Typography Scale - Matching iOS Design System
|
||||||
|
val AppTypography = Typography(
|
||||||
|
// Display - For hero sections
|
||||||
|
displayLarge = TextStyle(
|
||||||
|
fontSize = 57.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
lineHeight = 64.sp
|
||||||
|
),
|
||||||
|
displayMedium = TextStyle(
|
||||||
|
fontSize = 45.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
lineHeight = 52.sp
|
||||||
|
),
|
||||||
|
displaySmall = TextStyle(
|
||||||
|
fontSize = 36.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
lineHeight = 44.sp
|
||||||
|
),
|
||||||
|
|
||||||
|
// Headline - For section headers
|
||||||
|
headlineLarge = TextStyle(
|
||||||
|
fontSize = 32.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
lineHeight = 40.sp
|
||||||
|
),
|
||||||
|
headlineMedium = TextStyle(
|
||||||
|
fontSize = 28.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
lineHeight = 36.sp
|
||||||
|
),
|
||||||
|
headlineSmall = TextStyle(
|
||||||
|
fontSize = 24.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
lineHeight = 32.sp
|
||||||
|
),
|
||||||
|
|
||||||
|
// Title - For card titles
|
||||||
|
titleLarge = TextStyle(
|
||||||
|
fontSize = 22.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
lineHeight = 28.sp
|
||||||
|
),
|
||||||
|
titleMedium = TextStyle(
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
lineHeight = 24.sp
|
||||||
|
),
|
||||||
|
titleSmall = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
),
|
||||||
|
|
||||||
|
// Body - For main content
|
||||||
|
bodyLarge = TextStyle(
|
||||||
|
fontSize = 17.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
lineHeight = 24.sp
|
||||||
|
),
|
||||||
|
bodyMedium = TextStyle(
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
),
|
||||||
|
bodySmall = TextStyle(
|
||||||
|
fontSize = 13.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
lineHeight = 16.sp
|
||||||
|
),
|
||||||
|
|
||||||
|
// Label - For labels and captions
|
||||||
|
labelLarge = TextStyle(
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
),
|
||||||
|
labelMedium = TextStyle(
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
lineHeight = 16.sp
|
||||||
|
),
|
||||||
|
labelSmall = TextStyle(
|
||||||
|
fontSize = 11.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
lineHeight = 16.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user