@marioschmidt/design-system-tokens
v1.8.2
Published
BILD Design System Token Pipeline with Style Dictionary - Multi-brand design tokens for BILD, SportBILD, and Advertorial
Maintainers
Readme
🎨 BILD Design System - Token Pipeline
Part of the BILD Design Ops Pipeline | Icon Documentation | Component Documentation
Multi-platform design token transformation pipeline powered by Style Dictionary v4 with Figma-scoped semantic type detection.
📋 Table of Contents
- 🎯 Overview
- 🏗️ Pipeline Flow
- 📦 Installation
- 🚀 Quick Start
- 🎨 Platform Usage
- 📊 Token Transform Reference
- 📁 Output Structure
- 🔗 Figma Integration & Dependencies
- 🔄 CI/CD Workflows
- 🆘 Troubleshooting
- 🔗 Related
- 🤝 Contributing
- 📄 License
🎯 Overview
This pipeline processes the multi-layer, multi-brand BILD Design System architecture:
- 3 Brands: BILD, SportBILD, Advertorial
- 3 Platforms: Web (CSS, JSON), iOS (SwiftUI), Android (Compose)
- Multiple Modes: Density (3), Breakpoints (4), Color Modes (2)
- Token Types: Primitives, Semantic Tokens, Component Tokens (~970 files)
- Shadow DOM Compatible: Works with Stencil, Lit, and native Web Components
Token Architecture (4 Layers)
┌─────────────────────────────────────────────────────────────────────────────┐
│ LAYER 4: Component Tokens │
│ ───────────────────────────────────────────────────────────────────────── │
│ Button, Card, Teaser, Alert, InputField, etc. │
│ Modes: color (light/dark), density, breakpoint, typography │
│ References → Semantic Tokens │
├─────────────────────────────────────────────────────────────────────────────┤
│ LAYER 3: Semantic Tokens │
│ ───────────────────────────────────────────────────────────────────────── │
│ text-color-primary, surface-color-secondary, border-color-*, etc. │
│ Modes: color (light/dark), breakpoint │
│ References → Brand Mapping │
├─────────────────────────────────────────────────────────────────────────────┤
│ LAYER 2: Brand Mapping + Density │
│ ───────────────────────────────────────────────────────────────────────── │
│ BrandColorMapping: Color Primitives → Brands │
│ BrandTokenMapping: Other Primitives → Brands │
│ Density: default, dense, spacious │
│ Modes: BILD, SportBILD, Advertorial │
├─────────────────────────────────────────────────────────────────────────────┤
│ LAYER 1: Primitives (Global) │
│ ───────────────────────────────────────────────────────────────────────── │
│ colorprimitive, spaceprimitive, sizeprimitive, fontprimitive │
│ Absolute values: --bildred: #DD0000, --space2x: 16px │
└─────────────────────────────────────────────────────────────────────────────┘CSS var() Alias Chain
Tokens use var() references to maintain the alias chain from Figma:
/* Color: Component → Semantic → Primitive */
--button-primary-bg-color: var(--core-color-primary, #DD0000);
↓
--core-color-primary: var(--bildred, #DD0000);
↓
--bildred: #DD0000;
/* Spacing: BreakpointMode → Density → Primitive */
--stack-space-resp-md: var(--density-xs-stack-space-resp-md);
↓
--density-xs-stack-space-resp-md: var(--space-1-p-5-x, 12px);
↓
--space-1-p-5-x: 12px;
/* Shadow Effects: Mode-agnostic with var() for all properties */
[data-color-brand="bild"] .shadow-soft-sm {
box-shadow: var(--size-0-x, 0px) var(--size-0-p-25-x, 2px) ... var(--shadow-color-soft-key-sm);
}
/* Colors are theme-aware, dimensions are constant */This enables:
- Theme switching without recompiling (change primitives = change all)
- Brand switching via data attributes
- Density switching via
data-densityattribute (default/dense/spacious) - Mode-agnostic shadows with theme-aware colors via var()
- Conditional fallbacks (primitives get fallbacks, semantics don't)
Pipeline Flow
┌─────────────────────────────────────────────────┐
│ Figma Variables (Design Source) │
│ • BILD Design System file │
│ • Variables with Scopes & Aliases │
│ • CodeBridge plugin export │
└───────────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Raw Export (src/design-tokens/) │
│ • bild-design-system-raw-data.json │
└───────────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Preprocessing (scripts/tokens/preprocess.js) │
│ • Scope-based type determination │
│ • Alias resolution │
│ • Component token detection │
└───────────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Intermediate (tokens/) │
│ • Style Dictionary format │
│ • ~920 JSON files (tracked in Git) │
└───────────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Style Dictionary Build │
│ • Platform-specific transforms │
│ • iOS: CGFloat Points (not px strings) │
│ • iOS: SwiftUI Color │
└───────────────────────┬─────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Build Output (dist/) │
│ • 969 successful builds │
│ • NOT tracked in Git (CI artifacts) │
└─────────────────────────────────────────────────┘Installation
Web (npm)
npm install @marioschmidt/design-system-tokensiOS (Swift Package Manager)
In Xcode: File → Add Package Dependencies
URL: https://github.com/UXWizard25/bild-design-system.git
Product: BildDesignTokens✅ No authentication required (public repository)
Android (GitHub Packages Maven)
See packages/tokens-android/README.md for detailed setup instructions.
// build.gradle.kts
implementation("de.bild.design:tokens:1.0.0")⚠️ GitHub Packages requires authentication (GitHub Personal Access Token with
read:packagesscope)
Quick Start
# Full build (tokens + components)
npm run build
# Build tokens only
npm run build:tokens # Preprocess + Style Dictionary + bundles
# Build everything (tokens + icons + components)
npm run build:all
# Stencil Web Components
npm run build:components # Build Stencil components (requires tokens built first)
npm run dev:stencil # Dev server with hot reload (port 3333)Monorepo Structure
This package is part of the monorepo with platform-specific token packages:
| Package | Package Name | Location |
|---------|--------------|----------|
| Tokens (Web) | @marioschmidt/design-system-tokens (npm) | packages/tokens/ |
| Tokens (iOS) | BildDesignTokens (SPM) | packages/tokens-ios/ |
| Tokens (Android) | de.bild.design:tokens (Maven) | packages/tokens-android/ |
| Icons | @marioschmidt/design-system-icons (npm) | packages/icons/ |
| Components | @marioschmidt/design-system-components (npm) | packages/components/core/ |
| React | @marioschmidt/design-system-react (npm) | packages/components/react/ |
| Vue | @marioschmidt/design-system-vue (npm) | packages/components/vue/ |
Token Type Mapping
Figma token types ($type) are automatically mapped to platform-specific types:
| Figma $type | CSS | Swift (iOS) | Kotlin (Android) |
|---------------|-----|-------------|------------------|
| dimension | var(--token) (px) | CGFloat | Dp (.dp) |
| fontSize | var(--token) (px¹) | CGFloat | TextUnit (.sp) |
| lineHeight | var(--token) (unitless²) | CGFloat | TextUnit (.sp) |
| letterSpacing | var(--token) (px) | CGFloat | TextUnit (.sp) |
| fontWeight | var(--token) | FontWeight | FontWeight |
| number | var(--token) | CGFloat | Float |
| fontFamily | var(--token) | String | String |
| string | var(--token) | String | String |
| boolean | var(--token) | Bool | Boolean |
| opacity | var(--token) (0-1) | CGFloat | Float |
| color | var(--token) (hex/rgba) | Color | Color |
| shadow | box-shadow | ShadowStyle | ShadowStyle |
| typography | CSS classes | TextStyle | DesignTextStyle |
¹
fontSizeCSS unit is configurable viaFONT_SIZE_UNITinstyle-dictionary.config.js('px'or'rem'). Default:'px'. ²lineHeightCSS output is always unitless (ratio = lineHeight ÷ fontSize, e.g.,1.33). Scales proportionally with font-size.
Token Type Distribution
| $type | Count | Description |
|-------|-------|-------------|
| dimension | 3557 | Spacing, sizing, layout values |
| typography | 1356 | Composite font definitions |
| fontSize | 1086 | Font size values |
| color | 1012 | Color values (hex, rgba) |
| lineHeight | 840 | Line height values |
| fontWeight | 318 | Font weight values (100-1000) |
| fontFamily | 307 | Font family names |
| letterSpacing | 155 | Letter spacing values |
| string | 133 | String values (e.g., breakpoint names) |
| boolean | 102 | Boolean flags |
| shadow | 78 | Drop shadow definitions |
| opacity | 72 | Opacity percentages (0-100) |
| number | 24 | Generic numeric values |
Platform Usage
CSS
@import '@marioschmidt/design-system-tokens/css/brands/bild/semantic/color/colormode-light.css';
.button {
background-color: var(--text-color-accent-constant);
padding: var(--space2x);
opacity: var(--layer-opacity50);
}iOS Swift
import SwiftUI
import BildDesignTokens
// Colors (SwiftUI Color)
Rectangle()
.fill(BildColorsLight.textColorPrimary)
// Dimensions (CGFloat)
let padding: CGFloat = BildSizingCompact.space2x // 16
// With Theme Provider
.designSystemTheme(colorBrand: .bild, darkTheme: false) {
theme.colors.textColorPrimary
}Android Jetpack Compose (Dual-Axis Architecture)
See Android USAGE.md for complete documentation
import com.bild.designsystem.shared.DesignSystemTheme
import com.bild.designsystem.shared.ColorBrand
import com.bild.designsystem.shared.ContentBrand
import com.bild.designsystem.bild.components.ButtonTokens
@Composable
fun MyScreen() {
// Dual-Axis Theme Provider
DesignSystemTheme(
colorBrand = ColorBrand.Bild, // Color palette (Bild or Sportbild)
contentBrand = ContentBrand.Bild, // Sizing/Typography (Bild, Sportbild, Advertorial)
darkTheme = isSystemInDarkTheme(),
sizeClass = WindowSizeClass.Compact,
density = Density.Default
) {
// Polymorphic access via unified interfaces
Text(color = DesignSystemTheme.colors.textColorPrimary)
val fontSize = DesignSystemTheme.sizing.headline1FontSize
// Component tokens via current() accessors
val bgColor = ButtonTokens.Colors.current().buttonPrimaryBgColorIdle
}
}
// Advertorial with SportBILD colors (key use case)
DesignSystemTheme(
colorBrand = ColorBrand.Sportbild,
contentBrand = ContentBrand.Advertorial
) { AdvertorialContent() }Dual-Axis Architecture
Separates color selection from content selection:
| Axis | Enum | Values | Purpose |
|------|------|--------|---------|
| Color | ColorBrand | Bild, Sportbild | Color palette & effects |
| Content | ContentBrand | Bild, Sportbild, Advertorial | Sizing, typography, layout |
Unified Interfaces (Polymorphic Access)
Both iOS and Android implement identical unified protocols/interfaces for polymorphic theme access:
| Interface | Purpose | Property Count | iOS Type | Android Type |
|-----------|---------|----------------|----------|--------------|
| DesignColorScheme | All color tokens | 80+ colors | Color | Color |
| DesignSizingScheme | All sizing tokens | 180+ values | CGFloat | Dp |
| DesignTypographyScheme | All text styles | 37 styles | TextStyle | DesignTextStyle |
| DesignEffectsScheme | Shadow tokens (brand-independent) | 8 shadows | ShadowStyle | ShadowStyle |
| DesignDensityScheme | Density spacing tokens (brand-independent, internal) | 28 tokens | CGFloat | Dp |
Note: Full iOS/Android architecture parity. Both platforms provide
theme.colors,theme.sizing,theme.typography, andtheme.effectsaccessors with polymorphic brand switching at runtime.
Density-Aware Spacing (Consumer API)
Density tokens are internal and resolved automatically via BreakpointMode properties:
// Android - Use BreakpointMode token names (NOT densitySpacing directly)
@Composable
fun MyLayout() {
val respSpacing = DesignSystemTheme.stackSpaceRespMd // Responsive: varies by WindowSizeClass × Density
val constSpacing = DesignSystemTheme.stackSpaceConstLg // Constant: same across all WindowSizeClasses
Column(verticalArrangement = Arrangement.spacedBy(respSpacing)) {
// Content
}
}// iOS - Use BreakpointMode token names (NOT densitySpacing directly)
struct MyLayout: View {
@Environment(\.designSystemTheme) var theme
var body: some View {
VStack(spacing: theme.stackSpaceRespMd) { // Responsive: varies by SizeClass × Density
// Or constant: theme.stackSpaceConstLg // Same across all SizeClasses
}
}
}| Token Type | Example | Behavior |
|------------|---------|----------|
| Responsive | stackSpaceRespMd | Varies by WindowSizeClass/SizeClass × Density mode |
| Constant | stackSpaceConstLg | Same value across all WindowSizeClasses, varies by Density only |
Note: The
densitySpacingproperty is internal. Always use the semantic token names (stackSpaceRespMd,stackSpaceConstLg, etc.) which automatically resolve based on the currentsizeClassanddensitymode.
Important - Single Entry Point: Density-aware spacing tokens (
stackSpaceRespMd,stackSpaceConstLg, etc.) are NOT part ofDesignSizingScheme. They are only accessible viaDesignSystemThemeresolvers, which perform theWindowSizeClass × Densitymatrix lookup.
Component Token Accessors
All Component Tokens provide theme-aware current() accessors:
| Accessor | Selects based on | iOS Values | Android Values |
|----------|-----------------|------------|----------------|
| Colors.current() | isDarkTheme | Light / Dark | Light / Dark |
| Sizing.current() | sizeClass | Compact / Regular | Compact / Medium / Expanded |
| Typography.current() | sizeClass | Compact / Regular | Compact / Medium / Expanded |
| Density.current() | density | Dense / Default / Spacious | Dense / Default / Spacious |
| Effects.current() | isDarkTheme | Light / Dark | Light / Dark |
Note: Android uses Material 3 WindowSizeClass with 3 values (Compact/Medium/Expanded), while iOS uses Apple's 2-value system (compact/regular).
iOS SwiftUI (Dual-Axis Architecture)
See iOS USAGE.md for complete documentation
import SwiftUI
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.designSystemTheme(
colorBrand: .bild, // Color palette
contentBrand: .bild, // Sizing/Typography
darkTheme: false,
sizeClass: .compact
)
}
}
}
struct MyView: View {
@Environment(\.designSystemTheme) var theme
var body: some View {
// Polymorphic access via unified protocols
Text("Hello")
.foregroundColor(theme.colors.textColorPrimary)
.textStyle(theme.typography.headline1) // Typography
// Sizing tokens
let padding = theme.sizing.gridSpaceRespBase
// Component tokens
Button("Click") { }
.background(ButtonTokens.Colors.light.buttonPrimaryBrandBgColorIdle)
}
}
// Advertorial with SportBILD colors
.designSystemTheme(
colorBrand: .sportbild,
contentBrand: .advertorial
)iOS Unified Protocols
| Protocol | Purpose |
|----------|---------|
| DesignColorScheme | All color tokens |
| DesignSizingScheme | All sizing tokens |
| DesignTypographyScheme | All text styles (TextStyle composites) |
| DesignEffectsScheme | Shadow tokens (ShadowStyle composites, brand-independent) |
Web Components (Stencil, Lit)
CSS Custom Properties inherit through Shadow DOM, enabling seamless theming:
// Stencil Component
@Component({
tag: 'my-button',
shadow: true,
styles: `
.btn {
/* Token values inherit from Light DOM automatically! */
background: var(--button-primary-brand-bg-color-idle);
color: var(--button-primary-label-color);
padding: var(--button-stack-space) var(--button-inline-space);
border-radius: var(--button-border-radius);
}
.btn:hover {
background: var(--button-primary-brand-bg-color-hover);
}
`
})
export class MyButton { /* ... */ }<!-- Usage: Tokens on body, components inherit automatically -->
<body data-color-brand="bild" data-content-brand="bild" data-theme="light" data-density="default">
<my-button>BILD Button</my-button> <!-- Red -->
</body>
<body data-color-brand="sportbild" data-content-brand="sportbild" data-theme="dark" data-density="dense">
<my-button>Sport Button</my-button> <!-- Blue -->
</body>Theming Attributes:
| Attribute | Options | Purpose |
|-----------|---------|---------|
| data-color-brand | bild, sportbild | Colors & effects |
| data-content-brand | bild, sportbild, advertorial | Typography & sizing |
| data-theme | light, dark | Color mode |
| data-density | default, dense, spacious | Spacing density |
Note: See docs/css.md for complete Shadow DOM documentation.
Responsive CSS Architecture
Breakpoint Implementation
Breakpoints use native @media queries instead of data-breakpoint attributes:
/* Base values (xs breakpoint) */
[data-brand="bild"] {
--headline1-font-size: 32px;
}
/* Responsive overrides */
@media (min-width: 390px) { /* sm */
[data-brand="bild"] { --headline1-font-size: 40px; }
}
@media (min-width: 600px) { /* md */
[data-brand="bild"] { --headline1-font-size: 48px; }
}
@media (min-width: 1024px) { /* lg */
[data-brand="bild"] { --headline1-font-size: 64px; }
}Breakpoint Values:
| Breakpoint | Min-Width | Use Case |
|------------|-----------|----------|
| xs | 320px | Mobile (default) |
| sm | 390px | Large mobile |
| md | 600px | Tablet |
| lg | 1024px | Desktop |
Native Sizeclass Mapping (iOS/Android)
Native platforms use different size class systems:
iOS (2 Size Classes - Apple HIG)
Web Breakpoints iOS Size Classes
───────────────── ────────────────
xs (320px) ─────┐
├────→ compact (Phones)
sm (390px) ─────┘
md (600px) ─────┐
├────→ regular (Tablets)
lg (1024px) ────┘| Size Class | iOS Trait | Web Breakpoint |
|------------|-----------|----------------|
| compact | .compact | sm (390px) |
| regular | .regular | lg (1024px) |
Android (3 Size Classes - Material 3 WindowSizeClass)
Web Breakpoints Android WindowSizeClass
───────────────── ───────────────────────
xs (320px) ─────┐
├────→ Compact (< 600dp)
sm (390px) ─────┘
md (600px) ──────────→ Medium (600-839dp)
lg (1024px) ─────────→ Expanded (≥ 840dp)| Size Class | Material 3 Range | Web Breakpoint |
|------------|------------------|----------------|
| Compact | width < 600dp | sm (390px) |
| Medium | 600dp ≤ width < 840dp | md (600px) |
| Expanded | width ≥ 840dp | lg (1024px) |
Token Transform Reference
Naming Conventions
| Platform | Convention | Example |
|----------|-----------|---------|
| CSS | kebab-case with -- | --text-color-primary |
| iOS Swift | camelCase | textColorPrimary |
| Android Compose | camelCase | textColorPrimary |
Name Transformations
The pipeline applies these transformations to token names:
| Input | CSS/SCSS | JS/Swift/Compose | Notes |
|-------|----------|------------------|-------|
| TextColorPrimary | text-color-primary | textColorPrimary | CamelCase → kebab/camel |
| bildred | bildred | bildred | Lowercase preserved |
| bild085 | bild085 | bild085 | Numbers allowed |
| alpha-black-20 | alpha-black-20 | alphaBlack20 | Numbers at end OK |
| space2x | space2x | space2x | Dimension pattern |
| 700-black | 700-black | n700Black | Number prefix → n prefix |
Important: Tokens with numeric prefixes (e.g., 700-black-font-weight) get an n prefix in camelCase platforms to ensure valid identifiers.
Token Types
Colors
| Platform | Format | Example |
|----------|--------|---------|
| CSS | #HEX / rgba() | #DD0000 |
| iOS Swift | SwiftUI Color | Color(red: 0.867, ...) |
| Android Compose | Color(0xFF...) | Color(0xFFDD0000) |
Dimensions
| Platform | Format | Example |
|----------|--------|---------|
| CSS | Xpx (or Xrem for fontSize) | 16px, 1rem |
| iOS Swift | CGFloat number | 16 |
| Android Compose | X.dp | 16.dp |
Note: CSS
lineHeighttokens are unitless ratios (e.g.,1.33), not px. CSSfontSizeunit is controlled byFONT_SIZE_UNITsetting (default:px).
Typography (Compose)
Typography tokens in Compose use .sp for accessibility scaling:
| Property | Format | Example |
|----------|--------|---------|
| fontSize | X.sp | 16.sp |
| lineHeight | X.sp | 24.sp |
| letterSpacing | Xf.sp | 0.5f.sp |
| fontWeight | Int | 700 |
| fontStyle | FontStyle | FontStyle.Italic |
| fontFamily | String | "Gotham XNarrow" |
Opacity
| Platform | Format | Example |
|----------|--------|---------|
| CSS | 0-1 number | 0.5 |
| iOS Swift | CGFloat | 0.5 |
| Android Compose | Float | 0.5f |
Note: Figma exports opacity as percentage (5, 10, 70). Transform converts to decimal: 5 → 0.05. iOS/Swift uses per-token type detection to correctly map opacity tokens to CGFloat in component protocols.
Output Toggles
The build pipeline supports toggles to enable/disable specific outputs:
// In scripts/tokens/build.js
// Platform output toggles
const COMPOSE_ENABLED = true; // Enables dist/android/compose/ output
// Token type toggles
const BOOLEAN_TOKENS_ENABLED = false; // Excludes visibility tokens| Toggle | Default | Description |
|--------|---------|-------------|
| COMPOSE_ENABLED | true | Jetpack Compose Kotlin output in dist/android/compose/ |
| BOOLEAN_TOKENS_ENABLED | false | Boolean/visibility tokens (13 tokens like hideOnMobile) |
📁 Output Structure
Token outputs are distributed across three packages for platform-native distribution:
Web Package (packages/tokens/dist/)
packages/tokens/dist/
├── css/
│ ├── shared/ # Primitives
│ ├── bundles/ # Convenience bundles (Quick Start)
│ └── {brand}/
│ ├── density/
│ ├── components/ # ~48 component files
│ └── semantic/
└── json/ # Same structure as css/iOS Package (packages/tokens-ios/)
Distribution: Swift Package Manager (SPM) -
BildDesignTokens
packages/tokens-ios/
├── Package.swift # SPM manifest
├── README.md # Installation & usage docs
└── Sources/BildDesignTokens/ # 169 Swift files
├── shared/ # Primitives, protocols, theme provider
└── brands/{brand}/
├── semantic/ # Colors, sizing, typography
└── components/ # Component tokensAndroid Package (packages/tokens-android/)
Distribution: Maven via GitHub Packages -
de.bild.design:tokens
packages/tokens-android/
├── build.gradle.kts # Gradle build with Maven publishing
├── settings.gradle.kts
├── README.md # Installation & usage docs
└── src/main/kotlin/ # 182 Kotlin files
└── de/bild/design/tokens/
├── shared/
│ ├── DesignTokenPrimitives.kt # All primitives consolidated
│ ├── Density.kt # Dense/Default/Spacious enum
│ ├── WindowSizeClass.kt # Material 3: Compact/Medium/Expanded
│ ├── Brand.kt # Bild/Sportbild/Advertorial enum
│ └── DesignSystemTheme.kt # Multi-brand theme provider
└── brands/{brand}/
├── components/{Component}/
│ └── {Component}Tokens.kt # Aggregated with current() accessors
├── semantic/
│ ├── {Brand}SemanticTokens.kt
│ ├── color/
│ │ ├── ColorsLight.kt # BildColorScheme interface
│ │ └── ColorsDark.kt # BildDarkColors object
│ └── sizeclass/
│ ├── SizingCompact.kt # BildSizingScheme interface
│ ├── SizingMedium.kt # Material 3 Medium
│ └── SizingExpanded.kt # Material 3 Expanded
└── theme/
└── {Brand}Theme.kt # CompositionLocal Theme ProviderCompose File Organization
Compose output is optimized for Android development:
Shared Files (brand-independent):
| File | Content | Access Pattern |
|------|---------|----------------|
| shared/DesignTokenPrimitives.kt | All primitives (Colors, Space, Size, Font) | DesignTokenPrimitives.Colors.bildred |
| shared/Density.kt | UI density enum | Density.Dense, Density.Default, Density.Spacious |
| shared/WindowSizeClass.kt | Material 3 responsive layout enum | WindowSizeClass.Compact, WindowSizeClass.Medium, WindowSizeClass.Expanded |
| shared/ColorBrand.kt, ContentBrand.kt | Dual-axis brand enums | ColorBrand.Bild, ContentBrand.Advertorial |
| shared/DesignColorScheme.kt | Unified color interface | DesignSystemTheme.colors.textColorPrimary |
| shared/DesignSizingScheme.kt | Unified sizing interface | DesignSystemTheme.sizing.gridSpaceRespBase |
| shared/DesignTypographyScheme.kt | Unified typography interface | DesignSystemTheme.typography.headline1 |
| shared/DesignTextStyle.kt | Typography composite type | .toComposeTextStyle() |
| shared/DesignEffectsScheme.kt | Unified effects interface | DesignSystemTheme.effects.shadowSoftMd |
| shared/DropShadow.kt, ShadowStyle.kt | Shadow composite types | .toModifier() |
| shared/EffectsLight.kt, EffectsDark.kt | Light/Dark shadows | Brand-independent, only theme-dependent |
| shared/DesignSystemTheme.kt | Multi-brand theme provider | DesignSystemTheme(colorBrand, contentBrand) { } |
Brand Files:
| File | Content | Access Pattern |
|------|---------|----------------|
| {Brand}Theme.kt | CompositionLocal Theme Provider | BildTheme { }, BildTheme.colors.x, BildTheme.sizing.x |
| {Brand}SemanticTokens.kt | Colors + Sizing aggregated | BildSemanticTokens.Colors.Light.textColorPrimary |
| ColorsLight.kt / ColorsDark.kt | ColorScheme interface + impl | Used by BildTheme internally |
| SizingCompact.kt / SizingRegular.kt | SizingScheme interface + impl | Used by BildTheme internally |
| {Component}Tokens.kt | Component tokens with current() | ButtonTokens.Colors.current().buttonPrimaryBgColorIdle |
🔗 Figma Integration & Dependencies
Supported Figma Scopes
| Scope | Assigned Type | Output Format |
|-------|---------------|---------------|
| FONT_SIZE | fontSize | px/rem (CSS), .sp (Compose) |
| LINE_HEIGHT | lineHeight | unitless (CSS), .sp (Compose) |
| LETTER_SPACING | letterSpacing | px (CSS), .sp (Compose) |
| FONT_WEIGHT | fontWeight | Unitless integer (100-900) |
| FONT_FAMILY | fontFamily | String |
| FONT_STYLE | fontStyle | String, FontStyle.Italic (Compose) |
| OPACITY | opacity | 0-1 decimal (÷100) |
| WIDTH_HEIGHT | dimension | px (CSS), .dp (Compose) |
| GAP | dimension | px (CSS), .dp (Compose) |
| CORNER_RADIUS | dimension | px (CSS), .dp (Compose) |
| STROKE_FLOAT | dimension | px (CSS), .dp (Compose) |
| PARAGRAPH_SPACING | dimension | px (CSS), .dp (Compose) |
| PARAGRAPH_INDENT | dimension | px (CSS), .dp (Compose) |
| ALL_FILLS, FRAME_FILL, SHAPE_FILL, TEXT_FILL | color | #HEX, Color(0xFF...) |
| STROKE_COLOR, EFFECT_COLOR | color | #HEX, Color(0xFF...) |
Compose Unit Mapping
Android Compose uses type-safe units. The pipeline automatically maps token types:
| Token Type | Compose Unit | Example Output |
|------------|--------------|----------------|
| fontSize | .sp | 16.sp |
| lineHeight | .sp | 24.sp |
| letterSpacing | .sp | 0.5f.sp |
| dimension | .dp | 16.dp |
| fontWeight | Int | 700 |
| fontStyle | FontStyle | FontStyle.Italic |
| fontFamily | String | "Gotham XNarrow" |
| color | Color | Color(0xFFDD0000) |
| opacity | Int | 50 (percentage) |
Note: .sp (scale-independent pixels) is used for text-related measurements to support accessibility scaling. .dp (density-independent pixels) is used for layout dimensions.
Stable Changes
| Change Type | Impact | Auto-Recovery | |-------------|--------|---------------| | New token | Added | Yes | | Edit value | Updated | Yes | | Add scope | Better typing | Yes | | New component | Folder created | Yes |
Unstable Changes
| Change Type | Impact | Fix Required | |-------------|--------|--------------| | Delete collection | Build fails | Code update | | Rename collection | Tokens skipped | Code update | | Circular alias | Token unresolved | Fix in Figma |
🔄 CI/CD Workflows
build-tokens.yml
- Trigger: Push to main, develop, claude/**
- Outputs: Build artifacts (30-day retention)
auto-pr-from-figma.yml
- Trigger: Push to
figma-tokensbranch - Creates: Pull Request to main with release notes
publish-on-merge.yml
- Trigger: Push to main
- Actions: Impact-based version bump, npm publish, GitHub Release
Impact-Based Semantic Versioning
The publish workflow automatically determines the version bump based on token changes:
| Impact Level | Condition | Version Bump |
|--------------|-----------|--------------|
| breaking | Tokens/files removed | minor |
| moderate | Token values modified | patch |
| minor | Tokens/files added | patch |
| none | No token changes | patch |
The compare-builds.js script analyzes the diff between the current build and the previous release to calculate the impact level.
Race Condition Prevention
concurrency:
group: publish-main
cancel-in-progress: falseOnly one publish workflow runs at a time. Subsequent pushes queue and wait.
Synchronized Versioning
All packages (tokens, icons, components, react, vue) are published with the same version number.
🆘 Troubleshooting
Missing dist/ Folder
# Generate locally
npm run build
# Or download from CI artifactsBuild Failures
npm run clean
npm install
npm run buildiOS px String Issue
Fixed: iOS now uses custom/size/ios-points transform. Verify:
grep "Space2x" dist/ios/shared/Spaceprimitive.swift
# Expected: public static let Space2x = 16 (not "16px")🔗 Related
| Document | Description | |----------|-------------| | 📖 Main README | Project overview | | 📖 docs/css.md | CSS Custom Properties documentation | | 📖 Android USAGE.md | Android Jetpack Compose (Dual-Axis) | | 📖 iOS USAGE.md | iOS SwiftUI (Dual-Axis) | | 📖 Icons README | Icon pipeline documentation | | 📖 Components README | Stencil Web Components | | 📖 React README | React wrapper components | | 📖 Vue README | Vue 3 wrapper components | | Style Dictionary | Build tool documentation |
🤝 Contributing
⚠️ IMPORTANT: Figma is the Single Source of Truth
Design Tokens must NOT be edited directly in the repository. All token changes must be made in Figma and exported via the CodeBridge Plugin.
Workflow:
- Edit/create tokens in Figma
- Export with CodeBridge Plugin
- Review and merge PR
NOT Allowed:
- ❌ Direct changes to
src/design-tokens/*.json - ❌ Manual commits to
figma-tokensbranch - ❌ Changes to generated files in
dist/
Allowed (Pipeline Development):
- ✅ Changes to build scripts (
scripts/) - ✅ Changes to configuration (
build-config/) - ✅ Pipeline configuration (
build-config/pipeline.config.js- single source of truth) - ✅ Workflow adjustments (
.github/workflows/) - ✅ Documentation
Configuration:
- All pipeline settings are centralized in
build-config/pipeline.config.js - See PIPELINE-CONFIG.md for full documentation
📄 License
MIT License - See LICENSE file.
Built with ❤️ for the BILD Design System
| Feature | Status | |---------|--------| | 3 Platforms (Web, iOS, Android) | ✅ | | 3 Brands | ✅ | | ~970 Files | ✅ | | Figma Scopes | ✅ | | var() Aliases | ✅ | | Responsive CSS | ✅ | | Jetpack Compose | ✅ | | Theme Provider | ✅ | | Shadow DOM / Web Components | ✅ | | Stencil Components | ✅ |
