Kacheln und Fenster sprechen dieselbe Sprache

Alle Kacheln, Popovers und Fenster auf die Designschicht umgestellt: rund
hundert gesetzte Schriftgrößen und 159 gesetzte Abstände und Radien sind jetzt
Token. Übrig bleibt `spacing: 0` — das ist eine Aussage, keine geratene Zahl.

Die Einstellungen bekommen eine Seitenleiste statt sieben Reitern, deren
deutsche Beschriftungen zusammen 880 Punkte brauchten. Panel-Token stehen nicht
mehr in Fenstern: dort gilt Systemsemantik, damit der Hellmodus nicht schwarz
auf schwarz endet.

Neu ist ein Schaufenster, das alle Bauteile nebeneinander zeigt — ohne das
lässt sich eine Änderung an einem Token nur prüfen, indem man die App bedient,
bis jede Kachel einmal zu sehen war.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-09-05 21:05:51 +02:00
co-authored by Claude Opus 5
parent 9b600de9a9
commit edb327cabe
32 changed files with 3677 additions and 968 deletions
@@ -41,7 +41,7 @@ private struct Idle: View {
let model: MediaModel
var body: some View {
VStack(spacing: 8) {
VStack(spacing: Onyx.Space.md) {
Text("widget.media.nothing", bundle: .module)
.font(Onyx.Font.caption)
.foregroundStyle(Onyx.Color.textTertiary)
@@ -59,12 +59,12 @@ private struct Playing: View {
// Übereinander, nicht nebeneinander. Die Kachel ist hochkant: neben
// einem Cover blieben für den Titel noch gut hundert Punkte, und dann
// steht dort „Bernhard H…" statt eines Titels.
VStack(alignment: .leading, spacing: 7) {
VStack(alignment: .leading, spacing: Onyx.Space.md) {
Artwork(data: state.artwork)
.frame(maxWidth: .infinity)
.frame(height: 88)
VStack(alignment: .leading, spacing: 1) {
VStack(alignment: .leading, spacing: Onyx.Space.xxs) {
Text(state.title)
.font(Onyx.Font.caption.weight(.medium))
.foregroundStyle(Onyx.Color.textPrimary)
@@ -91,7 +91,7 @@ private struct Playing: View {
// greift: dann fehlen Cover und Browser-Wiedergaben,
// und das soll erklärbar sein statt rätselhaft.
Image(systemName: "applescript")
.font(.system(size: 9))
.font(.system(size: Onyx.Symbol.caption))
.foregroundStyle(Onyx.Color.textTertiary)
.help(Text("widget.media.viaAppleScript", bundle: .module))
}
@@ -107,7 +107,7 @@ private struct Artwork: View {
let data: Data?
var body: some View {
let shape = RoundedRectangle(cornerRadius: 8, style: .continuous)
let shape = RoundedRectangle(cornerRadius: Onyx.Radius.control, style: .continuous)
// Reihenfolge zählt: erst der Rahmen, dann das Beschneiden. Andersherum
// beschneidet man das Bild auf seine eigene, viel größere Größe — und es
@@ -122,7 +122,7 @@ private struct Artwork: View {
shape.fill(Onyx.Color.elevated)
.overlay {
Image(systemName: "music.note")
.font(.system(size: 18))
.font(.system(size: Onyx.Symbol.xlarge))
.foregroundStyle(Onyx.Color.textTertiary)
}
}
@@ -143,7 +143,7 @@ private struct Scrubber: View {
let now = model.tick
let progress = state.progress(at: now)
VStack(spacing: 2) {
VStack(spacing: Onyx.Space.xxs) {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Capsule().fill(Onyx.Color.hairline)
@@ -166,7 +166,7 @@ private struct Scrubber: View {
Spacer(minLength: 0)
Text(format(state.duration ?? 0))
}
.font(.system(size: 8))
.font(Onyx.Font.micro)
.monospacedDigit()
.foregroundStyle(Onyx.Color.textTertiary)
}
@@ -185,7 +185,7 @@ private struct TransportControls: View {
let size: CGFloat
var body: some View {
HStack(spacing: 12) {
HStack(spacing: Onyx.Space.lg) {
button("backward.fill") { model.send(.previous) }
button(model.nowPlaying?.isPlaying == true ? "pause.fill" : "play.fill") {
model.send(.playPause)