Skip to content

Commit 597e089

Browse files
Make Default Light/Dark follow Apple platform chrome.
Map Default themes to live system colors (window/control backgrounds, labels, controlAccentColor, systemRed/Green/…) so buttons and surfaces match stock macOS/iOS instead of the old grey Base16 palette.
1 parent 11f1346 commit 597e089

4 files changed

Lines changed: 235 additions & 69 deletions

File tree

Sources/TintedThemingSwift/Base16Theme.swift

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,35 +106,52 @@ public struct Base16Theme: Codable, Identifiable, Hashable {
106106

107107
// MARK: - Default Themes
108108
public extension Base16Theme {
109-
/// A default dark theme
109+
/// Default dark theme — Apple platform dark chrome (fallback hex ≈ system colors).
110+
/// On Apple platforms, SwiftUI/AppKit/UIKit color accessors resolve to live system
111+
/// colors (window/control backgrounds, label, controlAccentColor, systemRed…).
110112
static let defaultDark = Base16Theme(
111113
name: "Default Dark",
112-
author: "TintedThemes",
114+
author: "Apple Platform",
113115
variant: "dark",
114-
base00: "181818", base01: "282828", base02: "383838", base03: "585858",
115-
base04: "b8b8b8", base05: "d8d8d8", base06: "e8e8e8", base07: "f8f8f8",
116-
base08: "ab4642", base09: "dc9656", base0A: "f7ca88", base0B: "a1b56c",
117-
base0C: "86c1b9", base0D: "7cafc2", base0E: "ba8baf", base0F: "a16946"
116+
// Approximate macOS/iOS dark system palette (used off-platform / for YAML export).
117+
base00: "1C1C1E", base01: "2C2C2E", base02: "3A3A3C", base03: "8E8E93",
118+
base04: "AEAEB2", base05: "F2F2F7", base06: "EBEBF5", base07: "FFFFFF",
119+
base08: "FF453A", base09: "FF9F0A", base0A: "FFD60A", base0B: "30D158",
120+
base0C: "64D2FF", base0D: "0A84FF", base0E: "BF5AF2", base0F: "AC8E68"
118121
)
119-
120-
/// A default light theme
122+
123+
/// Default light theme — Apple platform light chrome (fallback hex ≈ system colors).
124+
/// On Apple platforms, color accessors resolve to live system colors.
121125
static let defaultLight = Base16Theme(
122126
name: "Default Light",
123-
author: "TintedThemes",
127+
author: "Apple Platform",
124128
variant: "light",
125-
base00: "f8f8f8", base01: "e8e8e8", base02: "d8d8d8", base03: "b8b8b8",
126-
base04: "585858", base05: "383838", base06: "282828", base07: "181818",
127-
base08: "ab4642", base09: "dc9656", base0A: "f7ca88", base0B: "a1b56c",
128-
base0C: "86c1b9", base0D: "7cafc2", base0E: "ba8baf", base0F: "a16946"
129+
// Approximate macOS/iOS light system palette (used off-platform / for YAML export).
130+
base00: "F5F5F7", base01: "FFFFFF", base02: "E5E5EA", base03: "8E8E93",
131+
base04: "636366", base05: "1C1C1E", base06: "3A3A3C", base07: "000000",
132+
base08: "FF3B30", base09: "FF9500", base0A: "FFCC00", base0B: "34C759",
133+
base0C: "5AC8FA", base0D: "007AFF", base0E: "AF52DE", base0F: "A2845E"
129134
)
130-
135+
131136
/// Returns true if this is a light theme
132137
var isLight: Bool {
133138
return variant == "light"
134139
}
135-
140+
136141
/// Returns true if this is a dark theme
137142
var isDark: Bool {
138143
return variant == "dark"
139144
}
145+
146+
/// Default Light / Default Dark map chrome + accents to stock Apple system colors
147+
/// (buttons, window/control backgrounds, labels, control accent).
148+
var usesApplePlatformChrome: Bool {
149+
(name == "Default Dark" || name == "Default Light")
150+
&& (author == "Apple Platform" || author == "TintedThemes")
151+
}
152+
153+
/// Whether this theme is one of the built-in Default Light / Default Dark presets.
154+
var isDefaultPlatformTheme: Bool {
155+
name == "Default Dark" || name == "Default Light"
156+
}
140157
}

Sources/TintedThemingSwift/ColorExtensions.swift

Lines changed: 83 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -34,39 +34,53 @@ public extension Color {
3434

3535
@available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *)
3636
public extension Base16Theme {
37+
/// SwiftUI Color for a Base16 index — Apple system colors when `usesApplePlatformChrome`.
38+
private func swiftUIPlatformColor(at index: Int, hex: String) -> Color {
39+
if usesApplePlatformChrome {
40+
#if canImport(AppKit) && !targetEnvironment(macCatalyst)
41+
return Color(nsColor: PlatformChrome.nsColor(for: self, index: index))
42+
#elseif canImport(UIKit)
43+
return Color(uiColor: PlatformChrome.uiColor(for: self, index: index))
44+
#else
45+
return Color(hex: hex)
46+
#endif
47+
}
48+
return Color(hex: hex)
49+
}
50+
3751
/// SwiftUI Color for base00 (Default Background)
38-
var swiftUIBase00Color: Color { Color(hex: base00) }
52+
var swiftUIBase00Color: Color { swiftUIPlatformColor(at: 0, hex: base00) }
3953
/// SwiftUI Color for base01 (Lighter Background)
40-
var swiftUIBase01Color: Color { Color(hex: base01) }
54+
var swiftUIBase01Color: Color { swiftUIPlatformColor(at: 1, hex: base01) }
4155
/// SwiftUI Color for base02 (Selection Background)
42-
var swiftUIBase02Color: Color { Color(hex: base02) }
56+
var swiftUIBase02Color: Color { swiftUIPlatformColor(at: 2, hex: base02) }
4357
/// SwiftUI Color for base03 (Comments, Invisibles)
44-
var swiftUIBase03Color: Color { Color(hex: base03) }
58+
var swiftUIBase03Color: Color { swiftUIPlatformColor(at: 3, hex: base03) }
4559
/// SwiftUI Color for base04 (Dark Foreground)
46-
var swiftUIBase04Color: Color { Color(hex: base04) }
60+
var swiftUIBase04Color: Color { swiftUIPlatformColor(at: 4, hex: base04) }
4761
/// SwiftUI Color for base05 (Default Foreground)
48-
var swiftUIBase05Color: Color { Color(hex: base05) }
62+
var swiftUIBase05Color: Color { swiftUIPlatformColor(at: 5, hex: base05) }
4963
/// SwiftUI Color for base06 (Light Foreground)
50-
var swiftUIBase06Color: Color { Color(hex: base06) }
64+
var swiftUIBase06Color: Color { swiftUIPlatformColor(at: 6, hex: base06) }
5165
/// SwiftUI Color for base07 (Light Background)
52-
var swiftUIBase07Color: Color { Color(hex: base07) }
66+
var swiftUIBase07Color: Color { swiftUIPlatformColor(at: 7, hex: base07) }
5367
/// SwiftUI Color for base08 (Variables, Red)
54-
var swiftUIBase08Color: Color { Color(hex: base08) }
68+
var swiftUIBase08Color: Color { swiftUIPlatformColor(at: 8, hex: base08) }
5569
/// SwiftUI Color for base09 (Integers, Orange)
56-
var swiftUIBase09Color: Color { Color(hex: base09) }
70+
var swiftUIBase09Color: Color { swiftUIPlatformColor(at: 9, hex: base09) }
5771
/// SwiftUI Color for base0A (Classes, Yellow)
58-
var swiftUIBase0AColor: Color { Color(hex: base0A) }
72+
var swiftUIBase0AColor: Color { swiftUIPlatformColor(at: 10, hex: base0A) }
5973
/// SwiftUI Color for base0B (Strings, Green)
60-
var swiftUIBase0BColor: Color { Color(hex: base0B) }
74+
var swiftUIBase0BColor: Color { swiftUIPlatformColor(at: 11, hex: base0B) }
6175
/// SwiftUI Color for base0C (Support, Cyan)
62-
var swiftUIBase0CColor: Color { Color(hex: base0C) }
63-
/// SwiftUI Color for base0D (Functions, Blue)
64-
var swiftUIBase0DColor: Color { Color(hex: base0D) }
76+
var swiftUIBase0CColor: Color { swiftUIPlatformColor(at: 12, hex: base0C) }
77+
/// SwiftUI Color for base0D (Functions, Blue / control accent)
78+
var swiftUIBase0DColor: Color { swiftUIPlatformColor(at: 13, hex: base0D) }
6579
/// SwiftUI Color for base0E (Keywords, Purple)
66-
var swiftUIBase0EColor: Color { Color(hex: base0E) }
80+
var swiftUIBase0EColor: Color { swiftUIPlatformColor(at: 14, hex: base0E) }
6781
/// SwiftUI Color for base0F (Deprecated, Brown)
68-
var swiftUIBase0FColor: Color { Color(hex: base0F) }
69-
82+
var swiftUIBase0FColor: Color { swiftUIPlatformColor(at: 15, hex: base0F) }
83+
7084
// Semantic color aliases
7185
var swiftUIBackgroundColor: Color { swiftUIBase00Color }
7286
var swiftUIForegroundColor: Color { swiftUIBase05Color }
@@ -174,39 +188,45 @@ public extension UIColor {
174188

175189
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)
176190
public extension Base16Theme {
191+
private func uiPlatformColor(at index: Int, hex: String) -> UIColor {
192+
usesApplePlatformChrome
193+
? PlatformChrome.uiColor(for: self, index: index)
194+
: UIColor(hex: hex)
195+
}
196+
177197
/// UIColor for base00 (Default Background)
178-
var uiBase00Color: UIColor { UIColor(hex: base00) }
198+
var uiBase00Color: UIColor { uiPlatformColor(at: 0, hex: base00) }
179199
/// UIColor for base01 (Lighter Background)
180-
var uiBase01Color: UIColor { UIColor(hex: base01) }
200+
var uiBase01Color: UIColor { uiPlatformColor(at: 1, hex: base01) }
181201
/// UIColor for base02 (Selection Background)
182-
var uiBase02Color: UIColor { UIColor(hex: base02) }
202+
var uiBase02Color: UIColor { uiPlatformColor(at: 2, hex: base02) }
183203
/// UIColor for base03 (Comments, Invisibles)
184-
var uiBase03Color: UIColor { UIColor(hex: base03) }
204+
var uiBase03Color: UIColor { uiPlatformColor(at: 3, hex: base03) }
185205
/// UIColor for base04 (Dark Foreground)
186-
var uiBase04Color: UIColor { UIColor(hex: base04) }
206+
var uiBase04Color: UIColor { uiPlatformColor(at: 4, hex: base04) }
187207
/// UIColor for base05 (Default Foreground)
188-
var uiBase05Color: UIColor { UIColor(hex: base05) }
208+
var uiBase05Color: UIColor { uiPlatformColor(at: 5, hex: base05) }
189209
/// UIColor for base06 (Light Foreground)
190-
var uiBase06Color: UIColor { UIColor(hex: base06) }
210+
var uiBase06Color: UIColor { uiPlatformColor(at: 6, hex: base06) }
191211
/// UIColor for base07 (Light Background)
192-
var uiBase07Color: UIColor { UIColor(hex: base07) }
212+
var uiBase07Color: UIColor { uiPlatformColor(at: 7, hex: base07) }
193213
/// UIColor for base08 (Variables, Red)
194-
var uiBase08Color: UIColor { UIColor(hex: base08) }
214+
var uiBase08Color: UIColor { uiPlatformColor(at: 8, hex: base08) }
195215
/// UIColor for base09 (Integers, Orange)
196-
var uiBase09Color: UIColor { UIColor(hex: base09) }
216+
var uiBase09Color: UIColor { uiPlatformColor(at: 9, hex: base09) }
197217
/// UIColor for base0A (Classes, Yellow)
198-
var uiBase0AColor: UIColor { UIColor(hex: base0A) }
218+
var uiBase0AColor: UIColor { uiPlatformColor(at: 10, hex: base0A) }
199219
/// UIColor for base0B (Strings, Green)
200-
var uiBase0BColor: UIColor { UIColor(hex: base0B) }
220+
var uiBase0BColor: UIColor { uiPlatformColor(at: 11, hex: base0B) }
201221
/// UIColor for base0C (Support, Cyan)
202-
var uiBase0CColor: UIColor { UIColor(hex: base0C) }
203-
/// UIColor for base0D (Functions, Blue)
204-
var uiBase0DColor: UIColor { UIColor(hex: base0D) }
222+
var uiBase0CColor: UIColor { uiPlatformColor(at: 12, hex: base0C) }
223+
/// UIColor for base0D (Functions, Blue / system accent)
224+
var uiBase0DColor: UIColor { uiPlatformColor(at: 13, hex: base0D) }
205225
/// UIColor for base0E (Keywords, Purple)
206-
var uiBase0EColor: UIColor { UIColor(hex: base0E) }
226+
var uiBase0EColor: UIColor { uiPlatformColor(at: 14, hex: base0E) }
207227
/// UIColor for base0F (Deprecated, Brown)
208-
var uiBase0FColor: UIColor { UIColor(hex: base0F) }
209-
228+
var uiBase0FColor: UIColor { uiPlatformColor(at: 15, hex: base0F) }
229+
210230
// Semantic color aliases
211231
var uiBackgroundColor: UIColor { uiBase00Color }
212232
var uiForegroundColor: UIColor { uiBase05Color }
@@ -252,39 +272,48 @@ public extension NSColor {
252272

253273
@available(macOS 10.15, *)
254274
public extension Base16Theme {
275+
private func nsPlatformColor(at index: Int, hex: String) -> NSColor {
276+
#if !targetEnvironment(macCatalyst)
277+
if usesApplePlatformChrome {
278+
return PlatformChrome.nsColor(for: self, index: index)
279+
}
280+
#endif
281+
return NSColor(hex: hex)
282+
}
283+
255284
/// NSColor for base00 (Default Background)
256-
var nsBase00Color: NSColor { NSColor(hex: base00) }
285+
var nsBase00Color: NSColor { nsPlatformColor(at: 0, hex: base00) }
257286
/// NSColor for base01 (Lighter Background)
258-
var nsBase01Color: NSColor { NSColor(hex: base01) }
287+
var nsBase01Color: NSColor { nsPlatformColor(at: 1, hex: base01) }
259288
/// NSColor for base02 (Selection Background)
260-
var nsBase02Color: NSColor { NSColor(hex: base02) }
289+
var nsBase02Color: NSColor { nsPlatformColor(at: 2, hex: base02) }
261290
/// NSColor for base03 (Comments, Invisibles)
262-
var nsBase03Color: NSColor { NSColor(hex: base03) }
291+
var nsBase03Color: NSColor { nsPlatformColor(at: 3, hex: base03) }
263292
/// NSColor for base04 (Dark Foreground)
264-
var nsBase04Color: NSColor { NSColor(hex: base04) }
293+
var nsBase04Color: NSColor { nsPlatformColor(at: 4, hex: base04) }
265294
/// NSColor for base05 (Default Foreground)
266-
var nsBase05Color: NSColor { NSColor(hex: base05) }
295+
var nsBase05Color: NSColor { nsPlatformColor(at: 5, hex: base05) }
267296
/// NSColor for base06 (Light Foreground)
268-
var nsBase06Color: NSColor { NSColor(hex: base06) }
297+
var nsBase06Color: NSColor { nsPlatformColor(at: 6, hex: base06) }
269298
/// NSColor for base07 (Light Background)
270-
var nsBase07Color: NSColor { NSColor(hex: base07) }
299+
var nsBase07Color: NSColor { nsPlatformColor(at: 7, hex: base07) }
271300
/// NSColor for base08 (Variables, Red)
272-
var nsBase08Color: NSColor { NSColor(hex: base08) }
301+
var nsBase08Color: NSColor { nsPlatformColor(at: 8, hex: base08) }
273302
/// NSColor for base09 (Integers, Orange)
274-
var nsBase09Color: NSColor { NSColor(hex: base09) }
303+
var nsBase09Color: NSColor { nsPlatformColor(at: 9, hex: base09) }
275304
/// NSColor for base0A (Classes, Yellow)
276-
var nsBase0AColor: NSColor { NSColor(hex: base0A) }
305+
var nsBase0AColor: NSColor { nsPlatformColor(at: 10, hex: base0A) }
277306
/// NSColor for base0B (Strings, Green)
278-
var nsBase0BColor: NSColor { NSColor(hex: base0B) }
307+
var nsBase0BColor: NSColor { nsPlatformColor(at: 11, hex: base0B) }
279308
/// NSColor for base0C (Support, Cyan)
280-
var nsBase0CColor: NSColor { NSColor(hex: base0C) }
281-
/// NSColor for base0D (Functions, Blue)
282-
var nsBase0DColor: NSColor { NSColor(hex: base0D) }
309+
var nsBase0CColor: NSColor { nsPlatformColor(at: 12, hex: base0C) }
310+
/// NSColor for base0D (Functions, Blue / controlAccentColor)
311+
var nsBase0DColor: NSColor { nsPlatformColor(at: 13, hex: base0D) }
283312
/// NSColor for base0E (Keywords, Purple)
284-
var nsBase0EColor: NSColor { NSColor(hex: base0E) }
313+
var nsBase0EColor: NSColor { nsPlatformColor(at: 14, hex: base0E) }
285314
/// NSColor for base0F (Deprecated, Brown)
286-
var nsBase0FColor: NSColor { NSColor(hex: base0F) }
287-
315+
var nsBase0FColor: NSColor { nsPlatformColor(at: 15, hex: base0F) }
316+
288317
// Semantic color aliases
289318
var nsBackgroundColor: NSColor { nsBase00Color }
290319
var nsForegroundColor: NSColor { nsBase05Color }
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import Foundation
2+
3+
#if canImport(AppKit) && !targetEnvironment(macCatalyst)
4+
import AppKit
5+
#endif
6+
#if canImport(UIKit)
7+
import UIKit
8+
#endif
9+
10+
/// Resolves Base16 slots to stock Apple platform colors for Default Light / Default Dark.
11+
enum PlatformChrome {
12+
/// Pick Default Light or Default Dark to match the current system appearance.
13+
public static func defaultMatchingSystemAppearance() -> Base16Theme {
14+
#if canImport(AppKit) && !targetEnvironment(macCatalyst)
15+
if #available(macOS 10.14, *) {
16+
let match = NSApp.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua])
17+
return match == .darkAqua ? .defaultDark : .defaultLight
18+
}
19+
return .defaultLight
20+
#elseif canImport(UIKit)
21+
switch UITraitCollection.current.userInterfaceStyle {
22+
case .dark: return .defaultDark
23+
default: return .defaultLight
24+
}
25+
#else
26+
return .defaultDark
27+
#endif
28+
}
29+
30+
#if canImport(AppKit) && !targetEnvironment(macCatalyst)
31+
/// Evaluate an NSColor under the appearance that matches the theme variant.
32+
static func nsColor(for theme: Base16Theme, index: Int) -> NSColor {
33+
guard theme.usesApplePlatformChrome else {
34+
return NSColor(hex: theme.color(at: index) ?? "000000")
35+
}
36+
let appearance = NSAppearance(named: theme.isLight ? .aqua : .darkAqua)
37+
?? NSAppearance(named: .aqua)
38+
var resolved: NSColor = .labelColor
39+
appearance?.performAsCurrentDrawingAppearance {
40+
resolved = nsSystemColor(index: index, light: theme.isLight)
41+
}
42+
return resolved
43+
}
44+
45+
private static func nsSystemColor(index: Int, light: Bool) -> NSColor {
46+
switch index {
47+
case 0: return .windowBackgroundColor
48+
case 1: return .controlBackgroundColor
49+
case 2:
50+
if #available(macOS 10.14, *) {
51+
return .selectedContentBackgroundColor
52+
}
53+
return .selectedTextBackgroundColor
54+
case 3: return .secondaryLabelColor
55+
case 4: return .secondaryLabelColor
56+
case 5: return .labelColor
57+
case 6: return .labelColor
58+
case 7: return light ? .black : .white
59+
case 8: return .systemRed
60+
case 9: return .systemOrange
61+
case 10: return .systemYellow
62+
case 11: return .systemGreen
63+
case 12:
64+
if #available(macOS 10.15, *) { return .systemTeal }
65+
return .systemBlue
66+
case 13: return .controlAccentColor
67+
case 14: return .systemPurple
68+
case 15: return .systemBrown
69+
default: return .labelColor
70+
}
71+
}
72+
#endif
73+
74+
#if canImport(UIKit)
75+
static func uiColor(for theme: Base16Theme, index: Int) -> UIColor {
76+
guard theme.usesApplePlatformChrome else {
77+
return UIColor(hex: theme.color(at: index) ?? "000000")
78+
}
79+
return uiSystemColor(index: index, light: theme.isLight)
80+
}
81+
82+
private static func uiSystemColor(index: Int, light: Bool) -> UIColor {
83+
switch index {
84+
case 0: return .systemBackground
85+
case 1: return .secondarySystemBackground
86+
case 2: return .tertiarySystemBackground
87+
case 3: return .secondaryLabel
88+
case 4: return .secondaryLabel
89+
case 5: return .label
90+
case 6: return .label
91+
case 7: return light ? .black : .white
92+
case 8: return .systemRed
93+
case 9: return .systemOrange
94+
case 10: return .systemYellow
95+
case 11: return .systemGreen
96+
case 12: return .systemTeal
97+
case 13: return .systemBlue // closest to control accent on iOS; apps may still use tint
98+
case 14: return .systemPurple
99+
case 15: return .systemBrown
100+
default: return .label
101+
}
102+
}
103+
#endif
104+
}
105+
106+
public extension Base16Theme {
107+
/// Default Light / Dark matching the current system appearance.
108+
static func defaultMatchingSystemAppearance() -> Base16Theme {
109+
PlatformChrome.defaultMatchingSystemAppearance()
110+
}
111+
}

0 commit comments

Comments
 (0)