From 1008a58cc39668c5f22ecf29437d7cce3b176a13 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 May 2026 16:27:25 +0000 Subject: [PATCH 1/2] Extract app colors to AppColors.swift Centralize theme color definitions in a single AppColors enum and update views to reference named colors instead of inline system colors. No visual changes in this commit. Co-authored-by: Greg --- Bedtime/Bedtime/Models/SleepData.swift | 10 +++--- Bedtime/Bedtime/Utils/AppColors.swift | 33 +++++++++++++++++++ .../Views/BedtimeRecommendationCard.swift | 4 +-- .../Views/Components/ProgressBar.swift | 6 ++-- .../Views/Components/SleepDayGroup.swift | 2 +- .../Views/HealthKitAuthorizationCard.swift | 4 +-- Bedtime/Bedtime/Views/LastNightCard.swift | 6 ++-- .../Views/RecentSleepSessionsCard.swift | 2 +- Bedtime/Bedtime/Views/SettingsView.swift | 12 +++---- Bedtime/Bedtime/Views/SleepBankCard.swift | 6 ++-- 10 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 Bedtime/Bedtime/Utils/AppColors.swift 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..a2d0d43 --- /dev/null +++ b/Bedtime/Bedtime/Utils/AppColors.swift @@ -0,0 +1,33 @@ +// +// AppColors.swift +// Bedtime +// + +import SwiftUI + +enum AppColors { + // MARK: - Accent + + static let accent = Color.blue + + // MARK: - Card accents + + static let bedtime = Color.blue + static let lastNight = Color.blue + static let recentSleep = Color.purple + static let healthKit = Color.red + + // MARK: - Status + + static let positive = Color.green + static let negative = Color.red + static let warning = Color.orange + + // MARK: - Sleep stages + + static let sleepDeep = Color.blue + static let sleepREM = Color.purple + static let sleepCore = Color.indigo + static let sleepAwake = Color.orange + static let sleepInBed = Color.gray +} 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..7dae95d 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, .cyan], 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) From b9d9e891cbb0351c54f9488a584d861791e2ad15 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 May 2026 16:28:53 +0000 Subject: [PATCH 2/2] Update colors to cozy theme matching app icon Replace the default system blues and purples with a warm palette inspired by the app icon: coral accents, cream backgrounds, dusty mauve and brown sleep-stage colors, and sage/terracotta status tones. Asset catalog colors now use adaptive light/dark cozy values. Co-authored-by: Greg --- .../AccentColor.colorset/Contents.json | 27 ++++++++++ .../Contents.json | 18 +++++-- .../CardBackground.colorset/Contents.json | 18 +++++-- Bedtime/Bedtime/Utils/AppColors.swift | 52 ++++++++++++++----- .../Views/Components/ProgressBar.swift | 2 +- 5 files changed, 95 insertions(+), 22 deletions(-) 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/Utils/AppColors.swift b/Bedtime/Bedtime/Utils/AppColors.swift index a2d0d43..0c86d10 100644 --- a/Bedtime/Bedtime/Utils/AppColors.swift +++ b/Bedtime/Bedtime/Utils/AppColors.swift @@ -8,26 +8,52 @@ import SwiftUI enum AppColors { // MARK: - Accent - static let accent = Color.blue + /// 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 = Color.blue - static let lastNight = Color.blue - static let recentSleep = Color.purple - static let healthKit = Color.red + 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 - static let positive = Color.green - static let negative = Color.red - static let warning = Color.orange + /// 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 - static let sleepDeep = Color.blue - static let sleepREM = Color.purple - static let sleepCore = Color.indigo - static let sleepAwake = Color.orange - static let sleepInBed = Color.gray + /// 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/Components/ProgressBar.swift b/Bedtime/Bedtime/Views/Components/ProgressBar.swift index 7dae95d..6308f7a 100644 --- a/Bedtime/Bedtime/Views/Components/ProgressBar.swift +++ b/Bedtime/Bedtime/Views/Components/ProgressBar.swift @@ -34,7 +34,7 @@ struct ProgressBar: View { .tint(Gradient(colors: [AppColors.recentSleep, AppColors.bedtime])) ProgressBar(value: 8, total: 10) - .tint(LinearGradient(colors: [AppColors.positive, .cyan], startPoint: .leading, endPoint: .trailing)) + .tint(LinearGradient(colors: [AppColors.positive, AppColors.accent], startPoint: .leading, endPoint: .trailing)) } .frame(height: 64) .padding()