Skip to main content
The Swift output has two halves. Generated token files hold statically resolved colors for each baked mode, and SubstrateKernel is a SwiftPM package containing a full port of the color math, for the cases where static values aren’t enough. Which half you need depends on how dynamic your app is. Static files alone cover light, dark, and the two high-contrast modes. Anything continuous — a mid-track scheme position, CVD compensation, custom contrast — requires the kernel.

What gets generated

Each brand emits a directory under generated/brands/<brand>/swift/:
There is no system.dimmed.gen.swift. Dimmed sits mid-track at scheme: 0.65, so it has no endpoint to bake — producing it requires continuous track sampling through SubstrateKernel. See Modes Overview.

The token files

Every per-mode file declares the same two top-level types: a SubstrateSystemTokenSet struct of exactly three colors, and a SubstrateSystemTokens enum of intent roles. This is example output for a fictional acme brand — generated/brands/acme/swift/system.light.gen.swift:
Three things to note:
  • Colors are Display P3, not sRGB. The Color(.displayP3, …) initializer is deliberate — the solver works in a wide gamut and the output preserves it.
  • Every intent is a surface/text/border triple. There are no primary/onPrimary pairs and no separate foreground roles.
  • There are no spacing or type-size constants. Those live in component style descriptors and are resolved by the kernel.
The intent roles in the enum are surface, surfaceElevated, brand, neutral, danger, warning, and success, plus whatever custom intents the brand declares.

Selecting a mode

Because all four files declare the same top-level names, they are alternative artifacts, not siblings. Adding two to one target collides on duplicate declarations. Pick one per build configuration, or wrap them behind your own conditional compilation.
If you want light and dark selected at runtime rather than at build time, either namespace the generated enums yourself or move to the kernel, which computes both from one brand definition.

SubstrateKernel

packages/kernel-swift is a SwiftPM package holding a pure-math port of the TypeScript kernel — no UI dependencies: UserPreferences mirrors the web vector exactly, with the same defaults:
The port is held to the TypeScript kernel by reference fixtures and per-brand conformance vectors, so a value computed in Swift matches the one the web runtime computes for the same inputs.

Component descriptors

Component styling ships as data, not code. Descriptors live in generated/global/swift/components/, with brand-specific overrides under the brand’s own swift/components/ directory. Each imports SubstrateKernel and describes a component as a tree of nodes and properties:
Spacing appears as .spatial(2) — a multiple of the space unit, resolved against the current densityFactor — rather than a fixed point value. That indirection is what lets density stay continuous. The per-brand index.gen.swift aggregates brand data and the resolved descriptor for each component into one entry point, keyed by component name.
Every generated file carries a @generated-substrate header and is a build artifact. Never edit one — changes belong in the brand YAML, then regenerate with npm run generate:tokens:swift from a Substrate checkout.

Android / Kotlin

The Compose mirror of this output, plus the Material ColorScheme bridge.

Modes Overview

Why four files exist and dimmed doesn’t, and what the preference vector controls.