Symbole folgen der Akzentfarbe, nicht der des Systems

SwiftUI zeichnet Symbole in Listen und Formularen auf macOS in der
Akzentfarbe des Systems — nicht in der des Fensters. `.tint` an der Wurzel
half deshalb nur der Reiterleiste; die Widget-Liste blieb systemgrün neben
einer blauen Leiste, obwohl beides derselben Einstellung folgen soll.

Ein eigener Label-Stil setzt die Farbe am Symbol. Er vererbt sich über die
Umgebung, also genügt eine Zeile an denselben vier Wurzeln, an denen auch der
Farbton gesetzt wird: Panel, Popovers, Einstellungen, Einrichtung.

Ein Symbol, das seine Farbe selbst mitbringt, behält sie — die innere Angabe
schlägt die äußere. Der grüne Haken für „erteilt" bringt sie jetzt am Symbol
mit statt am ganzen Label: Grün heißt dort „erteilt" und ist keine
Geschmacksfrage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-08-14 13:48:57 +02:00
parent fde3e864c0
commit 0df566d531
6 changed files with 50 additions and 7 deletions

View File

@@ -45,7 +45,8 @@ final class OnboardingWindowController: NSObject, NSWindowDelegate {
calendarModel: calendarModel, weatherModel: weatherModel, calendarModel: calendarModel, weatherModel: weatherModel,
mixer: mixer, fanControl: fanControl, launchAtLogin: launchAtLogin, mixer: mixer, fanControl: fanControl, launchAtLogin: launchAtLogin,
onFinish: { [weak self] in self?.finish() }) onFinish: { [weak self] in self?.finish() })
.tint(Onyx.Color.accent)) .tint(Onyx.Color.accent)
.labelStyle(.onyx))
let window = NSWindow(contentViewController: hosting) let window = NSWindow(contentViewController: hosting)
window.title = "Onyx" window.title = "Onyx"

View File

@@ -77,7 +77,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
rootView: NotchContainer(presentation: presentation) { rootView: NotchContainer(presentation: presentation) {
NotchPanelContent(model: model) NotchPanelContent(model: model)
} }
.tint(Onyx.Color.accent), .tint(Onyx.Color.accent)
.labelStyle(.onyx),
presentation: presentation) presentation: presentation)
} }
coordinator.start() coordinator.start()

View File

@@ -231,7 +231,15 @@ private struct PermissionRow: View {
Spacer() Spacer()
switch state { switch state {
case .granted: case .granted:
Label("settings.permissions.granted", systemImage: "checkmark.circle.fill") // Die Farbe sitzt am Symbol, nicht am ganzen Label: der
// Akzentstil färbt sonst darüber. Grün heißt hier erteilt"
// und ist keine Geschmacksfrage.
Label {
Text("settings.permissions.granted")
} icon: {
Image(systemName: "checkmark.circle.fill")
.foregroundStyle(Onyx.Color.positive)
}
.foregroundStyle(Onyx.Color.positive) .foregroundStyle(Onyx.Color.positive)
.labelStyle(.titleAndIcon) .labelStyle(.titleAndIcon)
case .undetermined: case .undetermined:

View File

@@ -65,7 +65,8 @@ final class SettingsWindowController: NSObject, NSWindowDelegate {
// Ohne das folgen Haken, Regler und Auswahlfelder der // Ohne das folgen Haken, Regler und Auswahlfelder der
// Systemfarbe statt der eingestellten. Genau daher kam das // Systemfarbe statt der eingestellten. Genau daher kam das
// Grün, das in Onyx sonst nirgends vorkommt. // Grün, das in Onyx sonst nirgends vorkommt.
.tint(Onyx.Color.accent)) .tint(Onyx.Color.accent)
.labelStyle(.onyx))
let window = NSWindow(contentViewController: hosting) let window = NSWindow(contentViewController: hosting)
window.title = "Onyx" window.title = "Onyx"

View File

@@ -0,0 +1,30 @@
import SwiftUI
/// Färbt das Symbol eines `Label` in der eingestellten Akzentfarbe.
///
/// **Nötig, weil `.tint` hier nicht greift.** SwiftUI zeichnet Symbole in
/// Listen und Formularen auf macOS in der Akzentfarbe des *Systems* nicht in
/// der des Fensters. Das Ergebnis war eine Widget-Liste in Systemgrün neben
/// einer Reiterleiste in Onyx-Blau, obwohl beides derselben Einstellung folgen
/// soll.
///
/// Ein Stil statt einer Farbe an jeder Fundstelle: er vererbt sich über die
/// Umgebung, also genügt eine Zeile an der Wurzel. Ein Symbol, das seine Farbe
/// selbst mitbringt etwa der grüne Haken für erteilt" , behält sie: die
/// innere Angabe schlägt die äußere.
public struct OnyxAccentLabelStyle: LabelStyle {
public init() {}
public func makeBody(configuration: Configuration) -> some View {
Label {
configuration.title
} icon: {
configuration.icon.foregroundStyle(Onyx.Color.accent)
}
}
}
public extension LabelStyle where Self == OnyxAccentLabelStyle {
static var onyx: OnyxAccentLabelStyle { OnyxAccentLabelStyle() }
}

View File

@@ -145,7 +145,9 @@ public final class MenuBarController {
// Auswahlfelder auf die Systemfarbe zurück das war der Grund, warum // Auswahlfelder auf die Systemfarbe zurück das war der Grund, warum
// die Popovers grün waren und die Widgets blau. // die Popovers grün waren und die Widgets blau.
entry.popover.contentViewController = NSHostingController( entry.popover.contentViewController = NSHostingController(
rootView: entry.module.makePopoverView().tint(Onyx.Color.accent)) rootView: entry.module.makePopoverView()
.tint(Onyx.Color.accent)
.labelStyle(.onyx))
entry.popover.show(relativeTo: sender.bounds, of: sender, preferredEdge: .minY) entry.popover.show(relativeTo: sender.bounds, of: sender, preferredEdge: .minY)
// Ohne das bleibt das Popover hinter dem aktiven Fenster. // Ohne das bleibt das Popover hinter dem aktiven Fenster.
entry.popover.contentViewController?.view.window?.makeKey() entry.popover.contentViewController?.view.window?.makeKey()