Theme configuration

Configure semantic color, spacing, radius, and typography.

An application theme conforms to FTheme. A minimal theme supplies spacing and radius scales plus Light and Dark Mode accent colors. Every other role has a FreakUI default.

Minimal theme

AppTheme.swift
import FreakUI

struct AppTheme: FTheme {
    let spacingScale: FSpacingScale = .medium
    let radiusScale: FRadiusScale = .medium

    let lightPrimaryAccent = "#1E506C"
    let darkPrimaryAccent = "#1FAEFF"
}

Activate the theme once, before creating the root interface:

YourApp.swift
import FreakUI
import SwiftUI

@main
struct YourApp: App {
    init() {
        FThemeManager.shared.configure(with: AppTheme())
    }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

Complete semantic palette

Themes can also override semantic success, warning, and destructive colors; primary, secondary, and tertiary backgrounds; and primary, secondary, and tertiary foregrounds for both appearances.

AppTheme.swift
struct AppTheme: FTheme {
    var spacingScale: FSpacingScale = .small
    var radiusScale: FRadiusScale = .medium

    var lightPrimaryAccent = "#29343B"
    var lightPrimaryGreen: String? = "#2F6B52"
    var lightPrimaryYellow: String? = "#7A5F18"
    var lightPrimaryRed: String? = "#96483D"
    var lightPrimaryBackground: String? = "#ECE9E3"
    var lightSecondaryBackground: String? = "#F4F1EB"
    var lightTertiaryBackground: String? = "#FBF9F5"
    var lightPrimaryFont: String? = "#172027"
    var lightSecondaryFont: String? = "#4D5961"
    var lightTertiaryFont: String? = "#5B666D"

    var darkPrimaryAccent = "#C2CCD1"
    var darkPrimaryGreen: String? = "#78B69A"
    var darkPrimaryYellow: String? = "#D0AE58"
    var darkPrimaryRed: String? = "#D89284"
    var darkPrimaryBackground: String? = "#0D0C0A"
    var darkSecondaryBackground: String? = "#191714"
    var darkTertiaryBackground: String? = "#26231F"
    var darkPrimaryFont: String? = "#EDF1F2"
    var darkSecondaryFont: String? = "#B5BEC2"
    var darkTertiaryFont: String? = "#929DA2"
}

Custom fonts

Custom font files belong to the client application target. Register them before configuring FThemeManager, then pass their PostScript names—not filenames—to FFontFaces.

AppTheme.swift
private extension FFontFaces {
    static let appText = FFontFaces(
        regular: "Satoshi-Regular",
        medium: "Satoshi-Medium",
        semibold: "Satoshi-Bold",
        bold: "Satoshi-Bold"
    )
}

struct AppTheme: FTheme {
    let spacingScale: FSpacingScale = .medium
    let radiusScale: FRadiusScale = .medium
    let typography = FTypography(
        textFamily: .custom(.appText),
        numberFamily: .systemMonospaced
    )

    let lightPrimaryAccent = "#1E506C"
    let darkPrimaryAccent = "#1FAEFF"
}

Theme colors accept opaque #RGB and #RRGGBB strings. Invalid colors and unavailable font faces fall back role by role and produce diagnostics in debug builds.

Continue with your first screen.