Files
onyx/Packages/OnyxKit/Sources/OnyxDesign/OnyxTokens.swift
Scarriffle 2aa60eedf9 Farben einstellbar — und erst mal überhaupt eine Farbe
Das Grün, das überall auftauchte, war die System-Akzentfarbe: `.tint` und
`.accentColor` werden ohne eigene Angabe dorthin durchgereicht, und das
betraf alle Popovers und das ganze Einstellungsfenster. Die Notch-Widgets
dagegen benutzten Onyx' eigenes Blau. Zwei Farben, ungewollt.

Jetzt eine, und die ist einstellbar. Ein neuer Reiter „Farben": Akzentfarbe
mit sechs Vorschlägen und einem Knopf, der die Systemfarbe übernimmt, dazu
das Paar für Herunter- und Hochladen samt Tauschknopf.

Die Signalfarben bleiben fest und stehen nur zur Ansicht dort. Gelb heißt
Warnung, Rot heißt kritisch, Grün heißt in Ordnung — bei Temperatur, Akku,
Lüfter und Fehlern. Wer sie umstellen kann, kann ihre Bedeutung zerstören;
ein rotes „alles gut" liest niemand richtig. Sichtbar sind sie trotzdem,
sonst sucht man die Warnfarbe im Reiter und findet sie nirgends.

Umgesetzt über die Tokens statt über vierzig Fundstellen: `Onyx.Color.accent`
ist keine Konstante mehr, sondern liest bei jedem Zugriff aus `OnyxTheme`.
Damit merkt SwiftUI die Abhängigkeit und zeichnet neu, sobald die Farbe sich
ändert. Dazu ein `.tint` an den vier Wurzeln — Panel, Popovers, Einstellungen,
Einrichtung —, damit auch Haken, Regler und Auswahlfelder mitziehen.

Nebenbei die Beschriftung: „Je Programm" heißt jetzt „Programme". Großgesetzt
las sich das als englisches „J-E".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 23:24:40 +02:00

89 lines
4.2 KiB
Swift

import SwiftUI
/// Die einzige Quelle für Farben, Maße und Bewegung in Onyx.
///
/// Onyx ist ein tiefschwarzer Stein mit feiner Bänderung und mattem Glanz kein
/// Glas. Das Panel benutzt deshalb bewusst **nicht** die Liquid-Glass-APIs von
/// macOS 26, sondern eine dunkle Vibrancy-Ebene mit eigenem Tint darüber.
public enum Onyx {
// MARK: - Farben
public enum Color {
/// Grundfläche des Panels.
public static let surface = SwiftUI.Color(red: 0.043, green: 0.043, blue: 0.051)
/// Kacheln auf der Grundfläche.
public static let elevated = SwiftUI.Color(red: 0.078, green: 0.078, blue: 0.090)
/// Innenkante der halbe edle" Effekt steckt in dieser einen Linie.
public static let hairline = SwiftUI.Color.white.opacity(0.08)
public static let textPrimary = SwiftUI.Color(red: 0.949, green: 0.949, blue: 0.957)
public static let textSecondary = SwiftUI.Color.white.opacity(0.58)
public static let textTertiary = SwiftUI.Color.white.opacity(0.34)
/// Die Farbe, mit der Onyx sich selbst zeichnet einstellbar.
///
/// Gelesen statt gespeichert: die Tokens holen den Wert bei jedem
/// Zugriff aus `OnyxTheme`. Damit merkt SwiftUI die Abhängigkeit und
/// zeichnet neu, sobald sich die Farbe ändert bei einer Konstanten
/// wären alle vierzig Fundstellen einzeln umzustellen gewesen.
@MainActor public static var accent: SwiftUI.Color { OnyxTheme.shared.accent }
/// Herunter- und Hochladen. Auch einstellbar: welche Richtung grün ist
/// und welche rosa, ist Gewohnheit, keine Bedeutung.
@MainActor public static var download: SwiftUI.Color { OnyxTheme.shared.download }
@MainActor public static var upload: SwiftUI.Color { OnyxTheme.shared.upload }
/// Die Signalfarben bleiben fest. Gelb heißt Warnung, Rot heißt
/// kritisch, Grün heißt in Ordnung wer das umstellen kann, kann die
/// Bedeutung zerstören.
public static let positive = SwiftUI.Color(red: 0.435, green: 0.812, blue: 0.592)
public static let warning = SwiftUI.Color(red: 0.910, green: 0.706, blue: 0.290)
public static let critical = SwiftUI.Color(red: 0.898, green: 0.404, blue: 0.361)
/// Deckkraft des Tints über der Vibrancy-Ebene. Darunter liest man den
/// Hintergrund durch, darüber wirkt das Panel wie eine schwarze Platte.
public static let surfaceOpacity: Double = 0.74
}
// MARK: - Maße
public enum Metric {
public static let panelCornerRadius: CGFloat = 26
public static let tileCornerRadius: CGFloat = 16
public static let panelPadding: CGFloat = 16
public static let tileSpacing: CGFloat = 10
public static let hairlineWidth: CGFloat = 1
}
// MARK: - Bewegung
public enum Motion {
/// Ausfahren: ein Spring mit einem Hauch Nachschwingen. Das gibt dem
/// Panel Masse, statt es nur größer werden zu lassen.
public static let expand = Animation.spring(response: 0.34, dampingFraction: 0.86)
/// Einfahren: kürzer und ohne Nachschwingen.
///
/// Schließen muss schneller sein als Öffnen. Beim Öffnen sieht man zu,
/// beim Schließen ist man schon woanders dieselbe Kurve rückwärts
/// fühlt sich dort zäh an, und das Nachschwingen liest sich als Ruckler.
public static let collapse = Animation.spring(response: 0.24, dampingFraction: 1.0)
/// Für Messwerte: sichtbar, aber ohne Pulsieren.
public static let value = Animation.easeOut(duration: 0.25)
}
// MARK: - Typografie
public enum Font {
public static let title = SwiftUI.Font.system(size: 13, weight: .semibold)
public static let body = SwiftUI.Font.system(size: 12, weight: .regular)
public static let caption = SwiftUI.Font.system(size: 10, weight: .medium)
/// Für alle Messwerte ohne feste Ziffernbreite zappeln die Zahlen.
public static let metric = SwiftUI.Font.system(size: 20, weight: .medium)
.monospacedDigit()
public static let metricSmall = SwiftUI.Font.system(size: 11, weight: .medium)
.monospacedDigit()
}
}