A Swift library for parsing and processing DTCG-compliant design tokens into type-safe Swift structures.
- โ Full DTCG format specification compliance
- ๐จ Support for all primitive token types (Color, Dimension, FontFamily, FontWeight, Duration, CubicBezier, Number)
- ๐งฉ Support for composite token types (StrokeStyle, Border, Transition, Shadow, Gradient, Typography)
- ๐ Token alias resolution with
{group.token}
syntax - ๐งฎ Dimension expression evaluation with arithmetic operations
- ๐ Unit conversion (px โ rem)
- ๐ Flexible token processing pipeline
- ๐พ Built-in file asset caching
- โก๏ธ Zero external dependencies
- ๐ฑ Cross-platform support (iOS, macOS, tvOS, watchOS, visionOS)
- iOS 16.0+ / macOS 13.0+
- Swift 6.1+
- Xcode 16.0+
Add SnappDesignTokens to your Package.swift
file:
dependencies: [
.package(url: "https://github.com/Snapp-Mobile/SnappDesignTokens.git", from: "1.0.0")
]
Or add it through Xcode:
- File > Add Package Dependencies...
- Enter package URL:
https://github.com/Snapp-Mobile/SnappDesignTokens.git
- Select version and add to your target
import SnappDesignTokens
import Foundation
// Load and parse DTCG-compliant JSON file
let url = Bundle.main.url(forResource: "tokens", withExtension: "json")!
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let token = try decoder.decode(Token.self, from: data)
// Access token values
if case .group(let group) = token,
case .value(.color(let colorValue)) = group["brand.primary"] {
print("Brand color: \(colorValue.hex)")
}
let jsonData = """
{
"color": {
"base": {
"red": { "$value": "#FF0000", "$type": "color" },
"blue": { "$value": "#0000FF", "$type": "color" }
}
}
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let token = try decoder.decode(Token.self, from: jsonData)
// Resolve aliases and flatten hierarchy
let processedToken = try await CombineProcessor.combine(
.resolveAliases,
.flatten()
).process(token)
// Alternative syntax
let processedToken = try await ResolveAliasesTokenProcessor
.resolveAliases
.combine(.flatten())
.process(token)
// Color tokens
if case .color(let color) = token.value {
print("Hex: \(color.hex)")
print("RGB: \(color.components)")
print("Alpha: \(color.alpha)")
}
// Dimension tokens
if case .dimension(let dimension) = token.value {
print("Value: \(dimension.value)")
print("Unit: \(dimension.unit)") // .px, .rem, etc.
}
// Typography tokens
if case .typography(let typography) = token.value {
print("Font: \(typography.fontFamily)")
print("Size: \(typography.fontSize)")
print("Weight: \(typography.fontWeight)")
}
let jsonData = """
{
"base": {
"color1": { "$value": "#FF0000", "$type": "color" },
"color2": { "$value": "{base.color1}" }
}
}
""".data(using: .utf8)!
let token: Token = try jsonData.decode()
let resolved = try await ResolveAliasesTokenProcessor
.resolveAliases
.process(token)
// base.color2 now contains #FF0000
let jsonData = """
{
"space1": { "$value": "2*2", "$type": "dimension" },
"space2": { "$value": "2", "$type": "dimension" }
}
""".data(using: .utf8)!
let token: Token = try jsonData.decode()
// Using arithmetical evaluation
let evaluated = try await DimensionValueEvaluationProcessor
.arithmeticalEvaluation
.process(token)
// space1 is now 4
// Or using NSExpression-based evaluation
let evaluated = try await DimensionValueEvaluationProcessor
.expressionsEvaluation
.process(token)
let token: Token = .group([
"dimension1": .value(.dimension(.constant(.init(value: 160, unit: .px)))),
"dimension2": .value(.dimension(.constant(.init(value: 1, unit: .rem))))
])
let processor: DimensionValueConversionProcessor = .dimensionValueConversion(
using: .converter(with: 16), // 1rem = 16px
targetUnit: .rem
)
let converted = try await processor.process(token)
// dimension1 is now 10rem, dimension2 remains 1rem
For more information about the DTCG specification, visit Design Tokens Community Group Format Specification.
Contributions are welcome! See CONTRIBUTING.md for guidelines.
SnappDesignTokens is available under the MIT license. See the LICENSE file for more info.