aboutsummaryrefslogtreecommitdiff
path: root/DomainDig/DomainDigUI.swift
diff options
context:
space:
mode:
Diffstat (limited to 'DomainDig/DomainDigUI.swift')
-rw-r--r--DomainDig/DomainDigUI.swift63
1 files changed, 55 insertions, 8 deletions
diff --git a/DomainDig/DomainDigUI.swift b/DomainDig/DomainDigUI.swift
index 7d99e4e..3aec259 100644
--- a/DomainDig/DomainDigUI.swift
+++ b/DomainDig/DomainDigUI.swift
@@ -120,6 +120,53 @@ extension EnvironmentValues {
}
}
+/// A status colour pairing: the foreground and the surface it sits on.
+///
+/// These travel together because they cannot be derived from one another. The
+/// badge fill used to be `foreground.opacity(0.16)`, which forced every
+/// foreground dark enough to stay legible against its own wash — that is how the
+/// light palette ended up olive-and-mud rather than amber-and-green. Decoupling
+/// them lets the foregrounds stay fully saturated.
+///
+/// See `Docs/ACCESSIBILITY.md` for the measured ratios.
+enum AppStatusTone {
+ case positive
+ case warning
+ case critical
+ case info
+ case neutral
+
+ var foreground: Color {
+ switch self {
+ case .positive:
+ return Color(.statusPositive)
+ case .warning:
+ return Color(.statusWarning)
+ case .critical:
+ return Color(.statusCritical)
+ case .info:
+ return Color(.statusInfo)
+ case .neutral:
+ return Color(.statusNeutral)
+ }
+ }
+
+ var surface: Color {
+ switch self {
+ case .positive:
+ return Color(.statusPositiveSurface)
+ case .warning:
+ return Color(.statusWarningSurface)
+ case .critical:
+ return Color(.statusCriticalSurface)
+ case .info:
+ return Color(.statusInfoSurface)
+ case .neutral:
+ return Color(.statusNeutralSurface)
+ }
+ }
+}
+
struct AppStatusBadgeModel: Equatable {
let title: String
let systemImage: String?
@@ -131,9 +178,9 @@ enum AppStatusFactory {
static func availability(_ status: DomainAvailabilityStatus?) -> AppStatusBadgeModel {
switch status {
case .available:
- return .init(title: "Available", systemImage: "checkmark.circle.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositive).opacity(0.16))
+ return .init(title: "Available", systemImage: "checkmark.circle.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositiveSurface))
case .registered:
- return .init(title: "Registered", systemImage: "circle.fill", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarning).opacity(0.16))
+ return .init(title: "Registered", systemImage: "circle.fill", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarningSurface))
case .unknown, .none:
return .init(title: "Unknown", systemImage: "questionmark.circle", foregroundColor: Color(.appTextSecondary), backgroundColor: Color(.appSurfaceElevated))
}
@@ -141,12 +188,12 @@ enum AppStatusFactory {
static func tls(sslInfo: SSLCertificateInfo?, error: String?) -> AppStatusBadgeModel {
if error != nil || sslInfo == nil {
- return .init(title: "Invalid", systemImage: "xmark.octagon.fill", foregroundColor: Color(.statusCritical), backgroundColor: Color(.statusCritical).opacity(0.16))
+ return .init(title: "Invalid", systemImage: "xmark.octagon.fill", foregroundColor: Color(.statusCritical), backgroundColor: Color(.statusCriticalSurface))
}
if let sslInfo, sslInfo.daysUntilExpiry <= 14 {
- return .init(title: "Expiring", systemImage: "exclamationmark.triangle.fill", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarning).opacity(0.16))
+ return .init(title: "Expiring", systemImage: "exclamationmark.triangle.fill", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarningSurface))
}
- return .init(title: "Valid", systemImage: "lock.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositive).opacity(0.16))
+ return .init(title: "Valid", systemImage: "lock.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositiveSurface))
}
static func email(_ result: EmailSecurityResult?, error: String?) -> AppStatusBadgeModel {
@@ -157,9 +204,9 @@ enum AppStatusFactory {
let foundCount = [result.spf.found, result.dmarc.found, result.dkim.found].filter { $0 }.count
switch foundCount {
case 3:
- return .init(title: "Secure", systemImage: "checkmark.shield.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositive).opacity(0.16))
+ return .init(title: "Secure", systemImage: "checkmark.shield.fill", foregroundColor: Color(.statusPositive), backgroundColor: Color(.statusPositiveSurface))
case 1, 2:
- return .init(title: "Partial", systemImage: "shield.lefthalf.filled", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarning).opacity(0.16))
+ return .init(title: "Partial", systemImage: "shield.lefthalf.filled", foregroundColor: Color(.statusWarning), backgroundColor: Color(.statusWarningSurface))
default:
return .init(title: "Missing", systemImage: "minus.circle", foregroundColor: Color(.appTextSecondary), backgroundColor: Color(.appSurfaceElevated))
}
@@ -170,7 +217,7 @@ enum AppStatusFactory {
return .init(title: "Unchanged", systemImage: "circle", foregroundColor: Color(.appTextSecondary), backgroundColor: Color(.appSurfaceElevated))
}
if summary.hasChanges {
- return .init(title: "Changed", systemImage: "arrow.triangle.2.circlepath", foregroundColor: Color(.statusInfo), backgroundColor: Color(.statusInfo).opacity(0.16))
+ return .init(title: "Changed", systemImage: "arrow.triangle.2.circlepath", foregroundColor: Color(.statusInfo), backgroundColor: Color(.statusInfoSurface))
}
return .init(title: "Unchanged", systemImage: "checkmark.circle", foregroundColor: Color(.appTextSecondary), backgroundColor: Color(.appSurfaceElevated))
}