@salesforce-ux/design-tokens
Version:
Salesforce Design System Tokens & Styling Hooks
468 lines (358 loc) • 17.1 kB
Markdown
# 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>