Theming
One environment value re-skins every screen and template.
Themed pieces read their colors, type, spacing, radii, elevation and motion from the Design System, a small set of Swift files in the SwiftUI environment. The CLI installs it with every screen and template. The reusable interactions inside screens (sheets, tab bars, cards) take their styling as parameters, so they drop into any codebase.
ContentView()
.environment(\.spTheme, PaperTheme())Themes
SystemThemeis the default. It follows iOS semantic colors, text styles and your app's AccentColor, so pieces look native until you give them a brand.PaperThemeis a warm editorial theme with serif headings, a terracotta accent, tighter corners and calmer springs. Use it as-is or as the reference for your own.- Your own theme is a struct conforming to
SPTheme. Every token struct has defaults, so override only what changes.
struct HarborTheme: SPTheme {
var color = SPColor(accent: .spDynamic(light: Color(spHex: 0x1F4D3A), dark: Color(spHex: 0x7FC7A0)))
var radius = SPRadius(lg: 18)
}Brands
A brand is a whole color scheme, not a tint. Each one sets the ground, a palette of solid color blocks with readable ink, the display face, numeral style, corner scale, motion and one graphic motif. Brands come from ten families:
- Studio: charcoal ground, pastel blocks, light-weight numerals, contour lines.
- Graphic: concrete grey, flat orange, violet and lemon blocks, heavy grotesk type, dot matrices.
- Editorial: paper ground, serif headlines, scenery drawn in code.
- Neon: near black with lime, Geist type, soft glow.
- Candy: cream ground, soft saturated blocks, rounded type and shapes.
- Ember: warm dark ground, coral and amber, serif captions, glow rings.
- Press: newsprint bone, printing inks, tabular figures, tight corners and hairline rules.
- Velvet: aubergine night, brass and jewel blocks, serif display, thin gilded rings.
- Frost: glacier white, steel and ice blocks, light numerals, thin concentric arcs.
- Sol: sun-bleached sand, marigold and terracotta, chunky grotesk, sunburst shapes.
SPBrandFonts.register()
ContentView()
.environment(\.spTheme, SPBrandTheme(.studio))Every template ships three presets from three different families, and every library preview shows its piece in one family. Put color on blocks with theme.color.tile(i) (use fill for the block and on for its text), and set hero figures with theme.type.numeral(_:relativeTo:).
Reading tokens in your own views
struct Summary: View {
@Environment(\.spTheme) private var theme
var body: some View {
Text("This week")
.font(theme.type.headline)
.foregroundStyle(theme.color.textPrimary)
.padding(theme.space.lg)
.spSurface(.e1, in: RoundedRectangle(cornerRadius: theme.radius.lg))
}
}Tokens
color:accent,accentOn,bg,surface,surfaceElevated,fill, the three text roles,separator,success,warning,danger,infoandglassTint. Build light and dark pairs withColor.spDynamic(light:dark:).type:displaythroughcaption. Bundled fonts should use.custom(_:size:relativeTo:)to keep Dynamic Type.space:xxsthroughxxxlon a 4pt grid, plusmarginfor screen edges.radius:xsthroughxlandpill.SPRadius.nested(in:padding:)keeps inner corners concentric.elevationandmotion: shadow levelse0toe4, andsnappy,smooth,bouncy,standardandheroanimations that shorten under Reduce Motion.
Modifiers
.spSurface(.e1, in: shape)fills with the surface color, applies the level's shadow and adds a hairline in dark mode..spShadow(.e2)applies a shadow level alone..spGlass(in: shape, interactive:)uses Liquid Glass on iOS 26, a material below, and an opaque fill when Reduce Transparency is on.