Files
Flaro/Packages/FlixyKit/Sources/FlixyDesign/FlixyFont.swift
T
ScarriffleandClaude Opus 5 d0f732402c Der Aufmacher endet an der Leiste, und durch sie sieht man nur noch gedämpft
Vier Dinge, die zusammengehören:

Die Spiegelung ist weg. `backgroundExtensionEffect` füllt die Fläche unter der
Leiste, indem er den Bildrand gespiegelt weiterzeichnet — und je größer die zu
füllende Fläche wurde, desto mehr übernahm der Spiegel das Bild. Auf dem iPhone
legte er sich ohne jede Seitenleiste über den Statusbalken. Jetzt läuft das
Bild selbst weiter, über einen negativen Rand.

Es endet dabei an der **Kante der Leiste**, nicht am Fensterrand. Der
Unterschied sind zwölf Punkte, und die waren deutlich zu sehen: neben der
schwebenden Leiste stand ein heller Streifen Bild, den nichts abdeckte.

Das Seitenverhältnis im Karussell musste weichen. Es legte den Aufmacher auf
die Breite des Inhaltsbereichs fest; weil er nach links unter die Leiste
greift, blieb rechts genau so viel schwarz übrig, wie er links gewann.

Und die Maße, in denen das Hintergrundbild angefordert wird, richten sich jetzt
nach dem Rahmen, in dem es landet. Vorher wurden 900×1200 geholt — hochkant —
und in einem 16:9-Rahmen gezeigt: zu sehen war ein Streifen aus der Mitte, oben
und unten fehlte je ein Drittel.

Dazu: auf schmalen Geräten ist der Aufmacher hochkant. In 16:9 blieben auf
einem iPhone keine zweihundertzwanzig Punkte Höhe, und Schriftzug, Zeile,
Beschreibung und zwei Knöpfe lagen übereinander.

Und ein Schleier unter dem Glas der Leiste. Reines Glas zeigt alles, was
dahinter vorbeizieht, und beim Scrollen zieht die ganze Startseite vorbei — aus
den ruhigen Beschriftungen wurde ein unruhiger Brei. Der Schleier nimmt der
Bewegung die Schärfe, ohne die Fläche zuzumauern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 20:05:07 +02:00

97 lines
4.4 KiB
Swift

import SwiftUI
/// Die Schriftskala der App.
///
/// Auf iOS die Systemstile, damit Dynamic Type wirkt. Die Rolle steht im
/// Namen, nicht die Größe — sonst führt jede Anpassung zu einer Suche quer
/// durch alle Views.
///
/// **Auf dem Mac stehen feste Größen.** Dieselben Stile sind dort deutlich
/// kleiner: `largeTitle` misst 26 Punkt statt 34, `body` 13 statt 17. Eine
/// Oberfläche, die auf dem iPad stimmt, wirkt damit auf dem Mac zusammen-
/// geschrumpft — und genau das war sie. Die Zahlen hier sind die von iOS.
///
/// Das kostet auf dem Mac Dynamic Type. Das ist vertretbar: macOS hat keine
/// systemweite Textgrößen-Einstellung, auf die Apps reagieren müssten, und ein
/// Fenster lässt sich stattdessen größer ziehen.
extension Font {
#if os(macOS)
/// Der Titel im Aufmacher-Bild.
public static let flixyHero = Font.system(size: 34, weight: .bold)
/// Titel auf Detailseiten.
public static let flixyTitle = Font.system(size: 22, weight: .semibold)
/// Überschrift einer Reihe auf der Startseite.
public static let flixyRowHeader = Font.system(size: 17, weight: .semibold)
/// Titel unter einem Poster.
public static let flixyCardTitle = Font.system(size: 15, weight: .medium)
/// Fließtext, Beschreibungen.
public static let flixyBody = Font.system(size: 17)
/// Jahreszahl, Laufzeit, Auflösung — alles, was neben dem Titel steht.
public static let flixyCaption = Font.system(size: 12)
#else
/// Der Titel im Aufmacher-Bild.
public static let flixyHero = Font.system(.largeTitle, design: .default, weight: .bold)
/// Titel auf Detailseiten.
public static let flixyTitle = Font.system(.title2, design: .default, weight: .semibold)
/// Überschrift einer Reihe auf der Startseite.
public static let flixyRowHeader = Font.system(.headline, design: .default, weight: .semibold)
/// Titel unter einem Poster.
public static let flixyCardTitle = Font.system(.subheadline, design: .default, weight: .medium)
/// Fließtext, Beschreibungen.
public static let flixyBody = Font.system(.body)
/// Jahreszahl, Laufzeit, Auflösung — alles, was neben dem Titel steht.
public static let flixyCaption = Font.system(.caption)
#endif
}
/// Abstände.
///
/// Eine Skala statt frei gewählter Zahlen: dadurch stimmen die Ränder zwischen
/// Bildschirmen überein, ohne dass man sie einzeln nachmisst.
public enum FlixySpacing {
public static let tight: CGFloat = 4
public static let snug: CGFloat = 8
public static let regular: CGFloat = 12
public static let loose: CGFloat = 16
public static let section: CGFloat = 24
/// Der seitliche Rand des Inhalts zum Bildschirmrand.
public static let screenMargin: CGFloat = 16
}
public enum FlixyRadius {
public static let card: CGFloat = 8
public static let sheet: CGFloat = 16
public static let control: CGFloat = 10
/// Eine schwebende Fläche — die Seitenleiste. So rund wie das System sie
/// auf dem iPad zeichnet; daran misst sich der Nachbau.
public static let panel: CGFloat = 22
}
/// Die Seitenverhältnisse, in denen Plex seine Bilder liefert.
///
/// An einer Stelle, weil ein falscher Wert nicht auffällt, sondern nur
/// beschneidet: ein 16:9-Hintergrundbild in einem 3:4-Rahmen verliert links
/// und rechts je ein Viertel, und man sieht dem Ergebnis nicht an, dass etwas
/// fehlt.
public enum FlixyAspectRatio {
/// Kinoplakate im Hochformat.
public static let poster: CGFloat = 2.0 / 3.0
/// Szenenbilder und Hintergrundbilder.
public static let landscape: CGFloat = 16.0 / 9.0
/// Der Aufmacher auf der Startseite — dasselbe wie `landscape`, weil Plex
/// dafür `art` liefert.
public static let hero: CGFloat = landscape
/// Der Aufmacher auf einem schmalen Bildschirm.
///
/// Nicht 16:9: auf einem iPhone sind das keine zweihundertzwanzig Punkte
/// Höhe, und darin sollen Titel oder Schriftzug, Zeile mit Jahr und Länge,
/// ein Satz Beschreibung und zwei Knöpfe Platz finden. Sie fanden ihn
/// nicht und lagen übereinander. Hochkant ist hier auch die ehrlichere
/// Form — ein Handy hält man so.
public static let heroCompact: CGFloat = 3.0 / 4.0
/// Sendersymbole. Breiter als hoch, weil Senderlogos Schriftzüge sind —
/// quadratisch beschnitten fehlt der halbe Name.
public static let channelLogo: CGFloat = 5.0 / 3.0
}