-
Notifications
You must be signed in to change notification settings - Fork 51
feat(appearance): use a light expanded dashboard #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
788155f
d0bc52e
0175a75
fdf4a2e
6dc55c1
34357ce
a7bf67f
de39590
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import SwiftUI | ||
|
|
||
| enum AppAppearance: String, CaseIterable, Hashable { | ||
| case system | ||
| case light | ||
| case dark | ||
|
|
||
| var label: String { | ||
| switch self { | ||
| case .system: "System" | ||
| case .light: "Light" | ||
| case .dark: "Dark" | ||
| } | ||
| } | ||
|
|
||
| var colorScheme: ColorScheme? { | ||
| switch self { | ||
| case .system: nil | ||
| case .light: .light | ||
| case .dark: .dark | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @MainActor | ||
| final class AppearanceStore: ObservableObject { | ||
| static let shared = AppearanceStore() | ||
| static let key = "MacIsland.appearance" | ||
|
|
||
| @Published var appearance: AppAppearance { | ||
| didSet { | ||
| UserDefaults.standard.set(appearance.rawValue, forKey: Self.key) | ||
| } | ||
| } | ||
|
|
||
| private init() { | ||
| let raw = UserDefaults.standard.string(forKey: Self.key) ?? "" | ||
| appearance = AppAppearance(rawValue: raw) ?? .dark | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,7 +1,19 @@ | ||||||
| import AppKit | ||||||
| import SwiftUI | ||||||
|
|
||||||
| /// Locked color tokens for CodexIsland. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Remove the generic
Proposed diff-/// Locked color tokens for CodexIsland.
enum IslandColor {As per coding guidelines, Swift files should default to no comments unless a comment explains a non-obvious constraint, workaround, or surprising behavior. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Coding guidelines |
||||||
| enum IslandColor { | ||||||
| static let settingsBackground = Color( | ||||||
| light: NSColor(calibratedWhite: 0.965, alpha: 1), | ||||||
| dark: NSColor(calibratedRed: 0.020, green: 0.020, blue: 0.027, alpha: 1) | ||||||
| ) | ||||||
|
|
||||||
| /// Expanded island surface in Light appearance. Compact and peek states | ||||||
| /// deliberately stay black so the notch silhouette remains unchanged. | ||||||
| static let expandedLightBackground = Color( | ||||||
| nsColor: NSColor(calibratedWhite: 0.955, alpha: 1) | ||||||
| ) | ||||||
|
|
||||||
| /// #0047AB — loading sweep, glow halo. | ||||||
| static let cobalt = Color(red: 0/255, green: 71/255, blue: 171/255) | ||||||
|
|
||||||
|
|
@@ -23,3 +35,11 @@ enum IslandColor { | |||||
| /// as "stop, you're cooked" without going full red-alert pure. | ||||||
| static let alertRed = Color(red: 229/255, green: 72/255, blue: 77/255) | ||||||
| } | ||||||
|
|
||||||
| private extension Color { | ||||||
| init(light: NSColor, dark: NSColor) { | ||||||
| self.init(nsColor: NSColor(name: nil) { appearance in | ||||||
| appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua ? dark : light | ||||||
| }) | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import SwiftUI | |
| struct CodexResetStatus: View { | ||
| @ObservedObject private var usageStore = UsageStore.shared | ||
| @ObservedObject private var visibility = ProviderVisibilityStore.shared | ||
| @Environment(\.colorScheme) private var colorScheme | ||
|
|
||
| @State private var showPopover = false | ||
| @State private var badgeHovered = false | ||
|
|
@@ -39,13 +40,13 @@ struct CodexResetStatus: View { | |
| .foregroundStyle(IslandColor.codex.opacity(badgeHovered || showPopover ? 1 : 0.8)) | ||
| Text(resetAvailabilityText) | ||
| .font(Typography.caption) | ||
| .foregroundStyle(.white.opacity(badgeHovered || showPopover ? 0.85 : 0.55)) | ||
| .foregroundStyle(Color.primary.opacity(badgeHovered || showPopover ? 0.85 : 0.55)) | ||
| } | ||
| .padding(.horizontal, 6) | ||
| .padding(.vertical, 3) | ||
| .background( | ||
| RoundedRectangle(cornerRadius: 5) | ||
| .fill(.white.opacity(badgeHovered || showPopover ? 0.05 : 0)) | ||
| .fill(Color.primary.opacity(badgeHovered || showPopover ? 0.05 : 0)) | ||
| ) | ||
| .contentShape(RoundedRectangle(cornerRadius: 5)) | ||
| .onHover { hovered in | ||
|
|
@@ -82,14 +83,14 @@ struct CodexResetStatus: View { | |
| .frame(width: 210, alignment: .leading) | ||
| .background( | ||
| RoundedRectangle(cornerRadius: 10) | ||
| .fill(.black) | ||
| .fill(colorScheme == .light ? IslandColor.expandedLightBackground : .black) | ||
| .overlay( | ||
| RoundedRectangle(cornerRadius: 10) | ||
| .fill(.white.opacity(0.04)) | ||
| .fill(Color.primary.opacity(0.04)) | ||
| ) | ||
| .overlay( | ||
| RoundedRectangle(cornerRadius: 10) | ||
| .strokeBorder(.white.opacity(0.10), lineWidth: 0.5) | ||
| .strokeBorder(Color.primary.opacity(0.10), lineWidth: 0.5) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ) | ||
| ) | ||
| .shadow(color: .black.opacity(0.5), radius: 16, y: 8) | ||
|
|
@@ -108,20 +109,20 @@ struct CodexResetStatus: View { | |
| Text(L10n.tr("EXPIRES")) | ||
| .font(Typography.sectionLabel) | ||
| .tracking(0.8) | ||
| .foregroundStyle(.white.opacity(0.40)) | ||
| .foregroundStyle(Color.primary.opacity(0.40)) | ||
| Spacer(minLength: 8) | ||
|
|
||
| Text(absolute(credit.expiresAt)) | ||
| .font(Typography.bodyNumber) | ||
| .foregroundStyle(.white.opacity(0.95)) | ||
| .foregroundStyle(Color.primary.opacity(0.95)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Light appearance—or System on a light macOS—is active and reset credits are available, this Useful? React with 👍 / 👎. |
||
| .lineLimit(1) | ||
| } | ||
| .frame(maxWidth: .infinity, alignment: .leading) | ||
| .padding(.horizontal, 8) | ||
| .padding(.vertical, 6) | ||
| .background( | ||
| RoundedRectangle(cornerRadius: 6) | ||
| .fill(.white.opacity(0.05)) | ||
| .fill(Color.primary.opacity(0.05)) | ||
| ) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Clarify the appearance option list.
light/dark/system appearanceis an ambiguous slash compound modifier. Uselight, dark, or system appearanceso the three options read clearly.Proposed wording
📝 Committable suggestion
🧰 Tools
🪛 LanguageTool
[uncategorized] ~187-~187: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...k/system appearance, Always show usage, Low Power Mode, configurable limit alerts, and ...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
🤖 Prompt for AI Agents
Source: Linters/SAST tools