feat(bar-app): retune subscription card palette for the dark theme

Replace the raw system green/yellow/orange/red headroom colors (garish on the
dark surface and colliding with the brand orange) with a muted, intuitive
green-amber-coral-red palette that leans coral for 'low' so a near-empty
window never reads as the accent. Drop the cool indigo card wash for a neutral
elevated surface so the warm bars no longer clash; subscription identity stays
on the section header and badge.
This commit is contained in:
Tam Nhu Tran
2026-06-09 15:13:56 -04:00
parent f22a8a0aee
commit 5aa94b5019
2 changed files with 23 additions and 10 deletions
@@ -36,7 +36,7 @@ struct BarSubscriptionCard: View {
.padding(.horizontal, 10)
.frame(maxWidth: .infinity, alignment: .leading)
.background(
BarTheme.subscription.opacity(0.07),
BarTheme.cardSurface,
in: RoundedRectangle(cornerRadius: 9))
}
@@ -53,7 +53,7 @@ struct BarSubscriptionCard: View {
.font(.system(.body, design: .default).weight(.semibold))
.lineLimit(1)
if row.needsReauth {
Chip("reauth", tint: .red)
Chip("reauth", tint: BarTheme.bandRed)
}
Spacer(minLength: 4)
if let tier = row.tier {
@@ -149,7 +149,7 @@ struct BarSubscriptionCard: View {
if isAtRisk, let pace = paceWarningText(for: w) {
Text(pace)
.font(.system(.caption2, design: .monospaced))
.foregroundStyle(.orange)
.foregroundStyle(BarTheme.bandCoral)
.lineLimit(1)
.padding(.leading, 5)
}
@@ -244,18 +244,18 @@ struct BarSubscriptionCard: View {
private var healthColor: Color {
switch row.health {
case "error": return .red
case "warning": return .orange
default: return .green
case "error": return BarTheme.bandRed
case "warning": return BarTheme.bandAmber
default: return BarTheme.bandGreen
}
}
private func color(for band: BarQuotaGauge.Band) -> Color {
switch band {
case .green: return .green
case .yellow: return .yellow
case .orange: return .orange
case .red: return .red
case .green: return BarTheme.bandGreen
case .yellow: return BarTheme.bandAmber
case .orange: return BarTheme.bandCoral
case .red: return BarTheme.bandRed
case .none: return .secondary
}
}
@@ -29,4 +29,17 @@ enum BarTheme {
/// so the user's own plan reads apart from CLIProxy pool accounts. A cool indigo
/// contrasts with the warm orange accent used for everything else.
static let subscription = Color(red: 0.357, green: 0.388, blue: 0.851) // ~#5B63D9
/// Headroom palette for quota bars. Muted for the dark surface (raw system
/// green/yellow/orange/red read garish here) and intuitive greenambercoralred.
/// Deliberately leans coral/red for "low" rather than the brand orange, so a
/// nearly-empty window never gets mistaken for the accent.
static let bandGreen = Color(red: 0.36, green: 0.74, blue: 0.56) // ~#5CBC8F emerald
static let bandAmber = Color(red: 0.86, green: 0.67, blue: 0.31) // ~#DBAB4F gold
static let bandCoral = Color(red: 0.91, green: 0.46, blue: 0.36) // ~#E8755C warning
static let bandRed = Color(red: 0.85, green: 0.34, blue: 0.31) // ~#D9564F critical
/// Neutral elevated surface for the subscription card a faint light lift
/// rather than a colored wash, so the warm headroom bars read cleanly on top.
static let cardSurface = Color.primary.opacity(0.05)
}