iOS Design Tokens
iOS Design Tokens
iOS design tokens bring systematic design values to iOS application development through Swift-native formats. Implementing tokens for iOS requires understanding UIKit and SwiftUI differences, Swift type systems, and how token pipelines generate appropriate outputs. Effective iOS token implementation enables consistent styling while embracing Swift idioms.
What Are iOS Design Tokens
iOS design tokens are design values stored in Swift code that iOS applications can reference with full type safety. Unlike CSS-based web tokens, iOS tokens exist as Swift constants, computed properties, or SwiftUI modifiers that integrate naturally with iOS development patterns.
Token transformation pipelines generate Swift files from platform-agnostic token definitions. The same source tokens that produce CSS custom properties also produce UIColor constants, CGFloat spacing values, and UIFont definitions for iOS.
How iOS Design Tokens Work
Token pipelines generate Swift files with strongly typed values:
import UIKit
import SwiftUI
public struct Tokens {
public struct Color {
public static let primary = UIColor(red: 0.231, green: 0.510, blue: 0.965, alpha: 1.0)
public static let backgroundDefault = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
public static let textPrimary = UIColor(red: 0.090, green: 0.090, blue: 0.090, alpha: 1.0)
}
public struct Spacing {
public static let sm: CGFloat = 8
public static let md: CGFloat = 16
public static let lg: CGFloat = 24
}
public struct Typography {
public static let bodyMd = UIFont.systemFont(ofSize: 16, weight: .regular)
public static let headingLg = UIFont.systemFont(ofSize: 24, weight: .bold)
}
}
UIKit applications reference these constants:
let button = UIButton()
button.backgroundColor = Tokens.Color.primary
button.titleLabel?.font = Tokens.Typography.bodyMd
button.contentEdgeInsets = UIEdgeInsets(
top: Tokens.Spacing.md,
left: Tokens.Spacing.lg,
bottom: Tokens.Spacing.md,
right: Tokens.Spacing.lg
)
SwiftUI tokens may include Color extensions for direct SwiftUI usage:
extension Color {
static let tokenPrimary = Color(Tokens.Color.primary)
static let tokenBackground = Color(Tokens.Color.backgroundDefault)
}
struct MyButton: View {
var body: some View {
Button("Click me") {}
.padding(.horizontal, Tokens.Spacing.lg)
.padding(.vertical, Tokens.Spacing.md)
.background(Color.tokenPrimary)
}
}
Key Considerations
- UIColor and SwiftUI Color are different types requiring conversion
- Swift’s type system catches invalid token usage at compile time
- Dynamic Type support requires scaled font handling
- Token updates require app recompilation and release
- Asset catalogs offer an alternative for colors but lack full token support
- Theming in iOS typically uses runtime color resolution
- Accessibility features like increased contrast need token variants
- Bundle size increases with token count but remains minimal
Common Questions
How should theming work on iOS?
iOS theming approaches differ from web-based runtime CSS variable switching. Since Swift constants are compile-time values, runtime theming requires different strategies.
Trait-based theming uses iOS trait collections to select colors:
extension UIColor {
static let primary = UIColor { traitCollection in
switch traitCollection.userInterfaceStyle {
case .dark:
return UIColor(red: 0.376, green: 0.647, blue: 0.996, alpha: 1.0)
default:
return UIColor(red: 0.231, green: 0.510, blue: 0.965, alpha: 1.0)
}
}
}
This approach leverages iOS’s native dark mode support, automatically updating when system appearance changes.
SwiftUI Environment enables component-level theming:
struct Theme {
var primary: Color
var background: Color
var text: Color
static let light = Theme(
primary: Color.tokenPrimary,
background: Color.tokenBackground,
text: Color.tokenText
)
static let dark = Theme(
primary: Color.tokenPrimaryDark,
background: Color.tokenBackgroundDark,
text: Color.tokenTextDark
)
}
struct ThemeKey: EnvironmentKey {
static let defaultValue = Theme.light
}
extension EnvironmentValues {
var theme: Theme {
get { self[ThemeKey.self] }
set { self[ThemeKey.self] = newValue }
}
}
Components access the theme through environment:
struct ThemedButton: View {
@Environment(\.theme) var theme
var body: some View {
Button("Click me") {}
.background(theme.primary)
}
}
How should typography tokens handle Dynamic Type?
iOS Dynamic Type allows users to adjust text size for accessibility. Token-based typography should support this feature.
Scaled fonts use UIFontMetrics to adjust sizes:
public struct Typography {
public static var bodyMd: UIFont {
let baseFont = UIFont.systemFont(ofSize: 16, weight: .regular)
return UIFontMetrics(forTextStyle: .body).scaledFont(for: baseFont)
}
}
Using computed properties instead of static constants ensures fonts scale appropriately.
SwiftUI provides built-in scaling:
Text("Hello")
.font(.system(size: 16))
.dynamicTypeSize(.large)
Token definitions can include text style mappings:
{
"typography": {
"body": {
"md": {
"value": {
"size": 16,
"weight": "regular",
"textStyle": "body"
}
}
}
}
}
Custom transforms generate scaled font code from these definitions.
How should token pipelines generate iOS outputs?
Style Dictionary configuration for iOS:
{
platforms: {
ios: {
transformGroup: 'ios-swift',
buildPath: 'ios/Sources/Tokens/',
files: [{
destination: 'Tokens.swift',
format: 'ios-swift/class.swift',
className: 'Tokens',
options: {
accessControl: 'public'
}
}]
},
iosSwiftUI: {
transformGroup: 'ios-swiftui',
buildPath: 'ios/Sources/Tokens/',
files: [{
destination: 'TokensSwiftUI.swift',
format: 'ios-swiftui/class.swift',
className: 'TokensSwiftUI'
}]
}
}
}
Custom formats may be needed for specific patterns like trait-based colors or scaled typography.
Build integration with Xcode can use build phases:
# Run script build phase
cd "$SRCROOT/../tokens"
npm run build-tokens
Swift Package Manager projects can include token generation in the package build process.
Summary
iOS design tokens enable systematic design value usage through Swift constants that integrate with UIKit and SwiftUI. Token pipelines generate type-safe Swift code from platform-agnostic definitions. Theming requires trait-based approaches or environment-based solutions rather than runtime variable switching. Typography tokens should support Dynamic Type for accessibility. Build automation ensures token generation integrates with iOS development workflows.
Buoy scans your codebase for design system inconsistencies before they ship
Detect Design Drift Free