# Salesforce Design Tokens

A Style Dictionary-based build system that transforms design tokens into platform-specific outputs (CSS custom properties, JSON metadata, Android/Kotlin, iOS/Swift).

## Key Features

- **W3C DTCG Format**: Tokens follow the [Design Tokens Community Group](https://www.designtokens.org/) specification
- **OKLCH Color Space**: Palette aliases defined in OKLCH perceptual color space, converted to hex for compatibility
- **Platform Agnostic**: Source tokens are not locked to CSS format
- **Dynamic CSS Variables**: Support for runtime-resolved CSS variable references
- **Light-Dark Function**: Automatic composition of `light-dark()` CSS functions for theme support
- **Theme Parity Validation**: Ensures global tokens match across all themes
- **Mobile Support**: Android (Kotlin) and iOS (Swift) outputs for Cosmos and Lightning Blue themes

## Quick Start

### Prerequisites

- Node.js >= 24.12.0
- Yarn >= 4.10.3

### Installation

This package is part of the Salesforce Design System monorepo. To work with design tokens:

```bash
# Clone the repository
git clone git@github.com:salesforce-ux/salesforce-design-system.git
cd salesforce-design-system

# Install dependencies
yarn install

# Build design tokens
cd packages/design-tokens
yarn build
```

### Commands

| Command                        | Description                           |
| ------------------------------ | ------------------------------------- |
| `yarn build`                   | Build all tokens                      |
| `yarn test`                    | Run all tests                         |
| `yarn test:watch`              | Run tests in watch mode               |
| `yarn test:coverage`           | Run tests with coverage report        |
| `yarn validate`                | Build + run all validators            |
| `yarn validate:dtcg`           | Run DTCG compliance validation        |
| `yarn validate:cross-platform` | Run cross-platform color validation   |
| `yarn validate:parity`         | Run theme parity validation           |

## Architecture Overview

### Build Pipeline

```mermaid
flowchart LR
    subgraph Sources["Source Tokens"]
        direction TB
        Common["common/"] ~~~ Cosmos["cosmos/"] ~~~ LightningBlue["lightning-blue/"]
    end

    subgraph Transforms
        direction TB
        T1["name/kebab"] ~~~ T2["value-unit-to-string"] ~~~ T3["css-vars"] ~~~ T4["light-dark-css-var"] ~~~ T5["oklch-to-hex"]
    end

    subgraph Filters
        direction TB
        F1["aliases"] ~~~ F2["global"] ~~~ F3["reference"] ~~~ F4["shared"] ~~~ F5["component"] ~~~ F6["deprecated"]
    end

    subgraph Outputs
        direction TB
        CSS["CSS"] ~~~ JSON["JSON"] ~~~ Android["Android"] ~~~ iOS["iOS"]
    end

    Sources --> Transforms
    Transforms --> Filters
    Filters --> Outputs
```

### Token Organization

```text
src/tokens/
├── common/                        # Shared across all themes
│   ├── alias-palettes.json          # OKLCH color definitions
│   ├── config.json                  # Configuration flags
│   ├── duration.json                # Duration tokens
│   ├── ratio.json                   # Ratio tokens (excluded from mobile outputs)
│   ├── sizing.json                  # Sizing tokens
│   └── spacing.json                 # Spacing tokens
├── cosmos/                        # Cosmos theme
│   ├── border-radius.json           # Border radius tokens
│   ├── font.json                    # Typography tokens
│   ├── raw-palettes.json            # Theme-specific OKLCH colors
│   ├── reference-palettes.json      # Reference palette tokens
│   ├── semantic-colors.json         # Semantic color tokens
│   ├── shadow.json                  # Shadow tokens (excluded from mobile outputs)
│   ├── system-colors.json           # System color tokens
│   ├── component/                   # Component-specific tokens
│   └── shared/                      # Shared component tokens
└── lightning-blue/                # Lightning Blue theme
    ├── border-radius.json           # Border radius tokens
    ├── font.json                    # Typography tokens
    ├── raw-palettes.json            # Theme-specific OKLCH colors
    ├── reference-palettes.json      # Reference palette tokens
    ├── semantic-colors.json         # Semantic color tokens
    ├── shadow.json                  # Shadow tokens (excluded from mobile outputs)
    ├── system-colors.json           # System color tokens
    ├── component/                   # Component-specific tokens
    └── shared/                      # Shared component tokens
```

### Output Structure

```text
dist/
├── config/
│   └── config.css                                   # Theme-independent config
└── themes/
    ├── cosmos/
    │   ├── android/                                   # Kotlin files (g, r, s)
    │   ├── ios/                                       # Swift files (g, r, s)
    │   ├── cosmos.deprecated.tokens.raw.json          # Deprecated tokens raw JSON
    │   ├── cosmos.global.tokens.css                   # Global CSS custom properties (g)
    │   ├── cosmos.global.tokens.flat.json             # Consumer JSON with un-prefixed token fields (g, r, s)
    │   ├── cosmos.global.tokens.raw.json              # DTCG-faithful JSON mirror ($ keys + metadata siblings)
    │   ├── cosmos.reference.tokens.css                # Reference scope CSS custom properties (r)
    │   ├── cosmos.reference.tokens.raw.json           # Reference scope raw JSON (r)
    │   ├── cosmos.shared.tokens.css                   # Shared scope CSS custom properties (s)
    │   └── cosmos.shared.tokens.raw.json              # Shared scope raw JSON (s)
    └── lightning-blue/
        ├── android/                                   # Kotlin files (g, r, s)
        ├── ios/                                       # Swift files (g, r, s)
        ├── lightning-blue.deprecated.tokens.raw.json  # Deprecated tokens raw JSON
        ├── lightning-blue.global.tokens.css           # Global CSS custom properties (g)
        ├── lightning-blue.global.tokens.flat.json     # Consumer JSON with un-prefixed token fields (g, r, s)
        ├── lightning-blue.global.tokens.raw.json      # DTCG-faithful JSON mirror ($ keys + metadata siblings)
        ├── lightning-blue.reference.tokens.css        # Reference scope CSS custom properties (r)
        ├── lightning-blue.reference.tokens.raw.json   # Reference scope raw JSON (r)
        ├── lightning-blue.shared.tokens.css           # Shared scope CSS custom properties (s)
        └── lightning-blue.shared.tokens.raw.json      # Shared scope raw JSON (s)
```

> **Note:** Deprecated tokens are included in all output formats. Mobile outputs (Android/iOS) annotate them with `@Deprecated` (Kotlin) and `@available(*, deprecated)` (Swift).

### Mobile Outputs

Android (Kotlin) and iOS (Swift) files are generated for both Cosmos and Lightning Blue themes:

**Cosmos Theme:**

- `dist/themes/cosmos/android/SalesforceCosmos*.kt` (10 files)
- `dist/themes/cosmos/ios/SalesforceCosmos*.swift` (10 files)

**Lightning Blue Theme:**

- `dist/themes/lightning-blue/android/SalesforceLightningBlue*.kt` (10 files)
- `dist/themes/lightning-blue/ios/SalesforceLightningBlue*.swift` (10 files)

Each theme generates:

- Spacing, Sizing, Shapes, MotionDuration, Fonts
- SystemColors, ReferenceColors, SemanticColors, PaletteColors
- TokensAll (combined file with all tokens)

## Token Scopes

Tokens are organized by scope, indicated by the second segment of the token path:

| Scope     | Path Pattern | Description                                     | CSS Output   |
| --------- | ------------ | ----------------------------------------------- | ------------ |
| Global    | `slds.g.*`   | Foundation tokens (colors, spacing, typography) | `--slds-g-*` |
| Reference | `slds.r.*`   | Reference tokens for theming                    | `--slds-r-*` |
| Shared    | `slds.s.*`   | Shared component tokens                         | `--slds-s-*` |
| Alias     | `alias.*`    | Internal aliases (filtered from output)         | N/A          |

See [Filters documentation](src/style-dictionary/filters/README.md#token-path-structure) for detailed information about token path structure and filtering.

## Token Syntax (W3C DTCG Format)

### Basic Token

```json
{
  "slds": {
    "g": {
      "spacing": {
        "$type": "dimension",
        "1": {
          "$value": {
            "value": 0.25,
            "unit": "rem"
          },
          "$description": "Spacing 1 | 4px."
        },
        ...
      }
    }
  }
}
```

### Token with Dark Mode

Tokens support dark mode via the `$extensions` property:

```json
{
  "slds": {
    "g": {
      "color": {
        "$type": "color",
        "surface": {
          "1": {
            "$value": "{alias.palette.neutral.100}",
            "$description": "Color surface used for page backgrounds.",
            "$extensions": {
              "com.salesforce-ux.mode": {
                "dark": {
                  "$value": "{alias.palette.neutral.15}"
                }
              }
            }
          },
          ...
        }
      }
    }
  }
}
```

**CSS Output:**

```css
--slds-g-color-surface-1: light-dark(#fff, #242424);
```

> **Note:** This example shows Cosmos theme output. Values may differ in other themes.

See the [Light-Dark CSS transform](src/style-dictionary/transforms/README.md#light-dark-css) documentation for detailed information about static and dynamic references.

### Dynamic CSS Variable References

By default, token references are resolved to their final values. Add `"dynamic": true` to output CSS variable references instead:

```json
{
  "slds": {
    "g": {
      "spacing": {
        "$type": "dimension",
        "1": {
          "$value": {
            "value": 0.25,
            "unit": "rem"
          },
          "$description": "Spacing 1 | 4px."
        },
        ...
        "var": {
          "1": {
            "$value": "{slds.g.spacing.1}",
            "$description": "Comfy (default) = 0.25rem | Compact = 0.125rem.",
            "dynamic": true
          }
        }
      }
    }
  }
}
```

**CSS Output:**

```css
--slds-g-spacing-1: 0.25rem;
--slds-g-spacing-var-1: var(--slds-g-spacing-1);
```

> **Note:** Shared (`slds.s.*`) and component (`slds.c.*`) scope tokens automatically use dynamic references.

See the [Dynamic CSS Variables transform](src/style-dictionary/transforms/README.md#dynamic-css-variables) documentation for detailed filter logic and examples.

### OKLCH Color Format

Colors can be defined in OKLCH color space for perceptual uniformity. OKLCH values are automatically converted to hex during the build process.

```json
{
  "alias": {
    "palette": {
      "$type": "color",
      "neutral": {
        "100": {
          "$value": {
            "colorSpace": "oklch",
            "components": [1, 0, 0]
          }
        }
      }
    }
  }
}
```

See the [OKLCH to Hex transform](src/style-dictionary/transforms/README.md#oklch-to-hex) documentation for implementation details.

## Build System

The build system uses [Style Dictionary v5](https://styledictionary.com/) with custom transforms, filters, and formats.

### Transform Order

Transforms are applied in a specific order for CSS output: `name/kebab` → `value/value-unit-to-string` → `value/css-vars` → `value/light-dark-css-var` → `value/oklch-to-hex`.

See [Transforms documentation](src/style-dictionary/transforms/README.md) for detailed information about each transform and their order.

### Build System Documentation

- [Transforms](src/style-dictionary/transforms/README.md) - Value transformation logic
- [Filters](src/style-dictionary/filters/README.md) - Token filtering by scope
- [Formats](src/style-dictionary/formats/README.md) - Output format generators

## Mobile Formatters

The package generates Android (Kotlin) and iOS (Swift) token files for the Cosmos theme only.

### Supported Types

| Type         | Description                 | Android      | iOS            |
| ------------ | --------------------------- | ------------ | -------------- |
| `color`      | Colors with light/dark mode | `Color`      | `Color`        |
| `dimension`  | Lengths (rem, px)           | `dp`         | `CGFloat`      |
| `duration`   | Time values                 | `ms`         | `TimeInterval` |
| `number`     | Unitless numbers            | `Float`      | `CGFloat`      |
| `fontWeight` | Font weights                | `FontWeight` | `Font.Weight`  |
| `fontFamily` | Font stacks                 | `FontFamily` | `Font`         |

### Exclusions

The following are excluded from mobile outputs (Android/iOS):

- **`shadow`** - Complex composite type requiring platform-specific shadow APIs
- **`ratio`** - CSS supports this natively
- **`ch` unit tokens** - The `ch` unit has no mobile equivalent; tokens using it (e.g., `sizing.content.*`, `sizing.heading.*`) are silently excluded since `convertDimensionToNumeric` only handles `px`, `rem`, and `%`

> **Note:** Deprecated tokens (`$deprecated: true`) are included in mobile outputs with platform-native annotations — `@Deprecated` (Kotlin) and `@available(*, deprecated)` (Swift).

See [Mobile Formats documentation](src/style-dictionary/formats/README.md#mobile-formats) for detailed information about architecture, configuration, and unit conversion.

## Validation

Validators ensure token quality and consistency across themes and platforms.

### Quick Reference

```bash
# Run all validators
yarn validate

# Run individual validators
yarn validate:dtcg                # DTCG compliance ($deprecated, $value, etc.)
yarn validate:cross-platform      # Cross-platform colors (CSS vs Android vs iOS)
yarn validate:parity              # Theme parity (Lightning Blue vs Cosmos)
```

See [Validators README](src/validators/README.md) for detailed documentation.

## Testing

Tests are written using [Vitest](https://vitest.dev/).

### Commands

```bash
# Run all tests
yarn test

# Run specific test files
yarn test:ios
yarn test:android

# Watch mode
yarn test:watch

# Coverage report
yarn test:coverage
```

### Test Organization

```text
src/__tests__/
├── filters/                         # Filter unit tests
│   └── mobile-filter.test.js          # Mobile filter tests
├── formats/                         # Format unit tests
├── transforms/                      # Transform unit tests
├── validators/                      # Validator tests
├── android-tokens.test.js           # Android output tests
├── build-outputs.test.js            # Build output snapshot tests
├── filters.test.js                  # Filter tests
├── ios-tokens.test.js               # iOS output tests
├── mobile-color-helpers.test.js     # Mobile color utility tests
├── mobile-helpers.test.js           # Mobile helper utility tests
└── value-unit-helpers.test.js       # Value/unit conversion tests
```

## CI/CD Pipeline

> ⚠️ **Note:** The CI/CD pipeline is currently work in progress and will be updated in a future release.

This section will be updated with documentation on:

- Automated builds
- Validation checks in CI
- Release process
- Version management

## Contributing

### Adding New Tokens

1. Add token definitions to the appropriate JSON file in `src/tokens/`
2. Follow the W3C DTCG format with `$type`, `$value`, and optional `$description`
3. For themed tokens, add both `cosmos/` and `lightning-blue/` versions
4. Run `yarn validate:parity` to ensure theme consistency

### Adding New Transformers/Filters/Formats

1. Create the implementation file in the appropriate directory
2. Export the registration function
3. Register in `src/style-dictionary/build.ts`
4. Add tests in `src/__tests__/`
5. Update the relevant README

---

<details open>
<summary><strong>Historical Notes</strong> (Migration Context)</summary>

### Migration from Theo

This package replaces the legacy `sds-styling-hooks` (Theo-based) and `sds-styling-aliases` packages. Key differences:

| Aspect      | Legacy (Theo)  | New (Style Dictionary) |
| ----------- | -------------- | ---------------------- |
| Format      | Theo YAML/JSON | W3C DTCG JSON          |
| Color Space | RGB/Hex only   | OKLCH with hex         |
| Dark Mode   | `light-dark()` | `$extensions`          |
| Mobile      | Not supported  | Android + iOS          |

### Temporary Validators

During migration, temporary validators (`temp-*.js`) compare outputs between the legacy and new systems. These will be removed after migration is complete.

### Deprecation Notice

The following packages will be deprecated after migration:

- `@salesforce-ux/sds-styling-hooks`
- `@salesforce-ux/sds-styling-aliases`

</details>
