UNPKG

@salesforce-ux/design-tokens

Version:

Salesforce Design System Tokens & Styling Hooks

468 lines (358 loc) • 17.1 kB
# 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>