diff --git a/Bedtime/Bedtime/Assets.xcassets/AccentColor.colorset/Contents.json b/Bedtime/Bedtime/Assets.xcassets/AccentColor.colorset/Contents.json index eb87897..7a778b5 100644 --- a/Bedtime/Bedtime/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/Bedtime/Bedtime/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,6 +1,33 @@ { "colors" : [ { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.486", + "green" : "0.596", + "red" : "0.973" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.573", + "green" : "0.659", + "red" : "0.961" + } + }, "idiom" : "universal" } ], diff --git a/Bedtime/Bedtime/Assets.xcassets/BackgroundBehindCards.colorset/Contents.json b/Bedtime/Bedtime/Assets.xcassets/BackgroundBehindCards.colorset/Contents.json index adc86b2..adfe964 100644 --- a/Bedtime/Bedtime/Assets.xcassets/BackgroundBehindCards.colorset/Contents.json +++ b/Bedtime/Bedtime/Assets.xcassets/BackgroundBehindCards.colorset/Contents.json @@ -2,8 +2,13 @@ "colors" : [ { "color" : { - "platform" : "ios", - "reference" : "secondarySystemBackgroundColor" + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.929", + "green" : "0.957", + "red" : "0.984" + } }, "idiom" : "universal" }, @@ -15,8 +20,13 @@ } ], "color" : { - "platform" : "ios", - "reference" : "systemBackgroundColor" + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.118", + "green" : "0.129", + "red" : "0.165" + } }, "idiom" : "universal" } diff --git a/Bedtime/Bedtime/Assets.xcassets/CardBackground.colorset/Contents.json b/Bedtime/Bedtime/Assets.xcassets/CardBackground.colorset/Contents.json index d551d24..5e4763b 100644 --- a/Bedtime/Bedtime/Assets.xcassets/CardBackground.colorset/Contents.json +++ b/Bedtime/Bedtime/Assets.xcassets/CardBackground.colorset/Contents.json @@ -2,8 +2,13 @@ "colors" : [ { "color" : { - "platform" : "ios", - "reference" : "systemBackgroundColor" + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.953", + "green" : "0.973", + "red" : "0.992" + } }, "idiom" : "universal" }, @@ -15,8 +20,13 @@ } ], "color" : { - "platform" : "ios", - "reference" : "tertiarySystemBackgroundColor" + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.173", + "green" : "0.196", + "red" : "0.239" + } }, "idiom" : "universal" } diff --git a/Bedtime/Bedtime/Models/SleepData.swift b/Bedtime/Bedtime/Models/SleepData.swift index 0020e59..6c40eda 100644 --- a/Bedtime/Bedtime/Models/SleepData.swift +++ b/Bedtime/Bedtime/Models/SleepData.swift @@ -74,11 +74,11 @@ extension HKCategoryValueSleepAnalysis { var color: Color { switch self { - case .asleepDeep: return Color.blue - case .asleepREM: return Color.purple - case .asleepCore: return Color.indigo - case .awake: return Color.orange - case .inBed: return Color.gray + case .asleepDeep: return AppColors.sleepDeep + case .asleepREM: return AppColors.sleepREM + case .asleepCore: return AppColors.sleepCore + case .awake: return AppColors.sleepAwake + case .inBed: return AppColors.sleepInBed case .asleepUnspecified: return Color.secondary @unknown default: return Color.secondary } diff --git a/Bedtime/Bedtime/Utils/AppColors.swift b/Bedtime/Bedtime/Utils/AppColors.swift new file mode 100644 index 0000000..0c86d10 --- /dev/null +++ b/Bedtime/Bedtime/Utils/AppColors.swift @@ -0,0 +1,59 @@ +// +// AppColors.swift +// Bedtime +// + +import SwiftUI + +enum AppColors { + // MARK: - Accent + + /// Warm coral from the app icon (#f8987c). + static let accent = cozyColor(light: (0.973, 0.596, 0.486), dark: (0.961, 0.659, 0.573)) + + // MARK: - Card accents + + static let bedtime = accent + static let lastNight = accent + + /// Dusty mauve brown from the icon (#9b786d). + static let recentSleep = cozyColor(light: (0.608, 0.471, 0.427), dark: (0.729, 0.588, 0.533)) + + /// Soft terracotta rose for health prompts. + static let healthKit = cozyColor(light: (0.788, 0.482, 0.420), dark: (0.878, 0.573, 0.506)) + + // MARK: - Status + + /// Muted sage green. + static let positive = cozyColor(light: (0.541, 0.671, 0.478), dark: (0.620, 0.749, 0.557)) + + /// Warm terracotta red. + static let negative = cozyColor(light: (0.788, 0.482, 0.420), dark: (0.878, 0.573, 0.506)) + + /// Soft amber peach. + static let warning = cozyColor(light: (0.910, 0.620, 0.451), dark: (0.941, 0.698, 0.541)) + + // MARK: - Sleep stages + + /// Deep warm brown (#826056). + static let sleepDeep = cozyColor(light: (0.510, 0.376, 0.337), dark: (0.639, 0.502, 0.463)) + + static let sleepREM = recentSleep + + /// Plum brown for core sleep. + static let sleepCore = cozyColor(light: (0.478, 0.345, 0.380), dark: (0.588, 0.455, 0.490)) + + static let sleepAwake = cozyColor(light: (0.969, 0.592, 0.482), dark: (0.980, 0.667, 0.573)) + + /// Warm taupe (#584744). + static let sleepInBed = cozyColor(light: (0.345, 0.278, 0.267), dark: (0.478, 0.404, 0.384)) + + private static func cozyColor(light: (Double, Double, Double), dark: (Double, Double, Double)) -> Color { + Color( + uiColor: UIColor { traits in + let rgb = traits.userInterfaceStyle == .dark ? dark : light + return UIColor(red: rgb.0, green: rgb.1, blue: rgb.2, alpha: 1) + } + ) + } +} diff --git a/Bedtime/Bedtime/Views/BedtimeRecommendationCard.swift b/Bedtime/Bedtime/Views/BedtimeRecommendationCard.swift index 8614134..63854b6 100644 --- a/Bedtime/Bedtime/Views/BedtimeRecommendationCard.swift +++ b/Bedtime/Bedtime/Views/BedtimeRecommendationCard.swift @@ -22,7 +22,7 @@ struct BedtimeRecommendationCard: View { HStack { Image(systemName: "bed.double.fill") .font(.title2) - .foregroundColor(.blue) + .foregroundColor(AppColors.bedtime) .frame(width: Constants.iconWidth) VStack(alignment: .leading, spacing: 4) { @@ -48,7 +48,7 @@ struct BedtimeRecommendationCard: View { Text(timeFormatter.string(from: recommendation.recommendedBedtime)) .font(.title) .fontWeight(.bold) - .foregroundColor(.blue) + .foregroundColor(AppColors.bedtime) } Spacer() diff --git a/Bedtime/Bedtime/Views/Components/ProgressBar.swift b/Bedtime/Bedtime/Views/Components/ProgressBar.swift index e647cfa..6308f7a 100644 --- a/Bedtime/Bedtime/Views/Components/ProgressBar.swift +++ b/Bedtime/Bedtime/Views/Components/ProgressBar.swift @@ -28,13 +28,13 @@ struct ProgressBar: View { #Preview(traits: .sizeThatFitsLayout) { VStack { ProgressBar(value: 0.2) - .tint(Gradient(colors: [.orange, .red])) + .tint(Gradient(colors: [AppColors.warning, AppColors.negative])) ProgressBar(value: 6, total: 8) - .tint(Gradient(colors: [.purple, .blue])) + .tint(Gradient(colors: [AppColors.recentSleep, AppColors.bedtime])) ProgressBar(value: 8, total: 10) - .tint(LinearGradient(colors: [.green, .cyan], startPoint: .leading, endPoint: .trailing)) + .tint(LinearGradient(colors: [AppColors.positive, AppColors.accent], startPoint: .leading, endPoint: .trailing)) } .frame(height: 64) .padding() diff --git a/Bedtime/Bedtime/Views/Components/SleepDayGroup.swift b/Bedtime/Bedtime/Views/Components/SleepDayGroup.swift index ce2a9cf..53888bc 100644 --- a/Bedtime/Bedtime/Views/Components/SleepDayGroup.swift +++ b/Bedtime/Bedtime/Views/Components/SleepDayGroup.swift @@ -29,7 +29,7 @@ struct SleepDayGroup: View { private var balanceImpact: (value: Double, isPositive: Bool, color: Color) { let totalSleepHours = sessions.map(\.durationInHours).reduce(0, +) let difference = totalSleepHours - sleepGoal - let color = difference >= 0 ? Color.green : difference < -0.5 ? Color.red : Color.secondary + let color = difference >= 0 ? AppColors.positive : difference < -0.5 ? AppColors.negative : Color.secondary return (abs(difference), difference >= 0, color) } diff --git a/Bedtime/Bedtime/Views/HealthKitAuthorizationCard.swift b/Bedtime/Bedtime/Views/HealthKitAuthorizationCard.swift index 8d5e223..731196c 100644 --- a/Bedtime/Bedtime/Views/HealthKitAuthorizationCard.swift +++ b/Bedtime/Bedtime/Views/HealthKitAuthorizationCard.swift @@ -16,7 +16,7 @@ struct HealthKitAuthorizationCard: View { HStack { Image(systemName: "heart.text.square") .font(.title2) - .foregroundColor(.red) + .foregroundColor(AppColors.healthKit) .frame(width: Constants.iconWidth) VStack(alignment: .leading, spacing: 4) { @@ -39,7 +39,7 @@ struct HealthKitAuthorizationCard: View { if let errorMessage = healthKitManager.errorMessage { Text(errorMessage) .font(.caption) - .foregroundColor(.red) + .foregroundColor(AppColors.healthKit) .multilineTextAlignment(.leading) } diff --git a/Bedtime/Bedtime/Views/LastNightCard.swift b/Bedtime/Bedtime/Views/LastNightCard.swift index ce02cbc..d460e95 100644 --- a/Bedtime/Bedtime/Views/LastNightCard.swift +++ b/Bedtime/Bedtime/Views/LastNightCard.swift @@ -27,7 +27,7 @@ struct LastNightCard: View { HStack { Image(systemName: "calendar") .font(.title2) - .foregroundColor(.blue) + .foregroundColor(AppColors.lastNight) .frame(width: Constants.iconWidth) VStack(alignment: .leading, spacing: 4) { Text("Last Night") @@ -64,7 +64,7 @@ struct LastNightCard: View { Text(String(format: "%.1f", durationInHours!)) .font(.title2) .fontWeight(.bold) - .foregroundStyle(durationInHours! > goal ? .green : .red) + .foregroundStyle(durationInHours! > goal ? AppColors.positive : AppColors.negative) Text("hours") .font(.subheadline) .foregroundColor(.secondary) @@ -74,7 +74,7 @@ struct LastNightCard: View { // Progress bar ProgressBar(value: durationInHours!, total: goal) - .tint(durationInHours! > goal ? .green : .red) + .tint(durationInHours! > goal ? AppColors.positive : AppColors.negative) } else { Text("No sleep data available") diff --git a/Bedtime/Bedtime/Views/RecentSleepSessionsCard.swift b/Bedtime/Bedtime/Views/RecentSleepSessionsCard.swift index e061641..83a4eb5 100644 --- a/Bedtime/Bedtime/Views/RecentSleepSessionsCard.swift +++ b/Bedtime/Bedtime/Views/RecentSleepSessionsCard.swift @@ -28,7 +28,7 @@ struct RecentSleepSessionsCard: View { HStack { Image(systemName: "chart.line.uptrend.xyaxis") .font(.title2) - .foregroundColor(.purple) + .foregroundColor(AppColors.recentSleep) .frame(width: Constants.iconWidth) VStack(alignment: .leading, spacing: 4) { diff --git a/Bedtime/Bedtime/Views/SettingsView.swift b/Bedtime/Bedtime/Views/SettingsView.swift index b38f34a..6b53847 100644 --- a/Bedtime/Bedtime/Views/SettingsView.swift +++ b/Bedtime/Bedtime/Views/SettingsView.swift @@ -38,7 +38,7 @@ struct SettingsView: View { Slider(value: $preferences.sleepGoalHours, in: 6...12, step: 0.25) { EmptyView() } - .accentColor(.blue) + .accentColor(AppColors.accent) } } @@ -62,7 +62,7 @@ struct SettingsView: View { Slider(value: sleepBankDaysBinding, in: 3...14, step: 1) { EmptyView() } - .accentColor(.blue) + .accentColor(AppColors.accent) Text("How many recent days to include in your sleep bank calculation") .font(.caption) @@ -82,7 +82,7 @@ struct SettingsView: View { Slider(value: $preferences.maxSleepHoursPerNight, in: 8...16, step: 1) { Text("Max") } - .accentColor(.blue) + .accentColor(AppColors.accent) HStack { Text("Min sleep hours per night") @@ -94,7 +94,7 @@ struct SettingsView: View { Slider(value: $preferences.minSleepHoursPerNight, in: 2...10, step: 1) { Text("Min") } - .accentColor(.blue) + .accentColor(AppColors.accent) } } @@ -134,14 +134,14 @@ struct SettingsView: View { }) { Text("Source \(bundleIdentifier) is no longer available. Tap to delete.") .font(.caption) - .foregroundColor(.orange) + .foregroundColor(AppColors.warning) } } if allExcluded { Text("No sources selected. Sleep data will not be displayed.") .font(.caption) - .foregroundColor(.orange) + .foregroundColor(AppColors.warning) } } else { diff --git a/Bedtime/Bedtime/Views/SleepBankCard.swift b/Bedtime/Bedtime/Views/SleepBankCard.swift index de8daa7..888f896 100644 --- a/Bedtime/Bedtime/Views/SleepBankCard.swift +++ b/Bedtime/Bedtime/Views/SleepBankCard.swift @@ -16,7 +16,7 @@ struct SleepBankCard: View { HStack { Image(systemName: sleepBank.isInDebt ? "moon.zzz.fill" : "moon.stars.fill") .font(.title2) - .foregroundColor(sleepBank.averageHours == nil ? .secondary : sleepBank.isInDebt ? .red : .green) + .foregroundColor(sleepBank.averageHours == nil ? .secondary : sleepBank.isInDebt ? AppColors.negative : AppColors.positive) .frame(width: Constants.iconWidth) VStack(alignment: .leading, spacing: 4) { @@ -44,7 +44,7 @@ struct SleepBankCard: View { Text(String(format: "%.1f", averageHours)) .font(.title2) .fontWeight(.bold) - .foregroundColor(sleepBank.isInDebt ? .red : .green) + .foregroundColor(sleepBank.isInDebt ? AppColors.negative : AppColors.positive) Text("hours") .font(.subheadline) .foregroundColor(.secondary) @@ -69,7 +69,7 @@ struct SleepBankCard: View { Text(String(format: "%.1f", abs(sleepBank.currentBalance))) .font(.title2) .fontWeight(.bold) - .foregroundColor(sleepBank.isInDebt ? .red : .green) + .foregroundColor(sleepBank.isInDebt ? AppColors.negative : AppColors.positive) Text("hours \(sleepBank.isInDebt ? "behind" : "ahead")") .font(.subheadline)