Style Dictionary

repository·main·Indexed 26 days ago

https://github.com/style-dictionary/style-dictionary

A build system for creating cross-platform styles using design tokens. It allows developers to define styles once and export them to multiple platforms and languages, such as iOS, Android, CSS, and JS. Version 5.5.0 features a CLI for building, cleaning, and initializing projects, as well as a Node.js module for custom build scripts, support for Category/Type/Item (CTI) token structures, and the ability to register custom transforms.

Tokens
40.5K
Snippets
132
Records
204
Agent score
81%

What's inside style-dictionary

  1. Understand the Style Dictionary build pipeline

    main

    Style Dictionary operates through a multi-stage pipeline that transforms raw design tokens into platform-specific code. The process follows these nine steps:

    1. Parse the config: Reads your configuration file to determine the build instructions.
    2. Find all token files: Uses include and source globs from your config to locate token files.
    3. Parse token files: Uses built-in or custom parsers to convert files into JavaScript objects.
    4. Deep merge token files: Combines all parsed objects into a single, complete dictionary.
    5. Run preprocessors: Executes custom preprocessors on the merged dictionary (either globally or at the platform level).
    6. Transform the tokens: Traverses the dictionary and applies transforms to any token containing a value key.
    7. Resolve aliases: Replaces references (e.g., "{size.font.base}") with their transformed values.
    8. Format the tokens: Uses formats to turn the resolved dictionary into specific file outputs.
    9. Run actions: Executes actions after files are generated (e.g., for asset copying or image generation).
  2. Organize tokens using Category / Type / Item (CTI) structure

    main

    While not required, organizing tokens in a hierarchical tree structure (Category $\rightarrow$ Type $\rightarrow$ Item) provides consistent naming and enables powerful helpers.

    For example, a structure like size.font.base implicitly defines:

    • Category: size
    • Type: font
    • Item: base

    Using this structure allows you to use the 'attribute/cti' transform to automatically add attributes to tokens based on their object path, which can then be used for filtering or further transformations.

    {
      "size": {
        "font": {
          "base": { "value": "16" },
          "large": { "value": "20" }
        }
      }
    }
  3. Register a preprocessor

    main

    You can register a preprocessor using one of two methods:

    1. Using .registerPreprocessor: Call this method on the StyleDictionary class to make the preprocessor available globally.
    2. Inline in configuration: Define the preprocessor directly within the hooks.preprocessors property of your configuration object.
    // Method 1: .registerPreprocessor
    import StyleDictionary from 'style-dictionary';
    StyleDictionary.registerPreprocessor(myPreprocessor);
    
    // Method 2: Inline in config
    export default {
      hooks: {
        preprocessors: {
          'strip-props': myPreprocessor,
        },
      },
      // ... the rest of the configuration
    };
  4. Structure a Style Dictionary package

    main

    Style Dictionary is configuration-driven. A complete package must include a configuration file and a reference to a path containing design token files. You may optionally include an assets directory to maintain a single source of truth for files like images, vectors, or fonts.

    Required components:

    • Configuration file: Typically config.json, where you define the execution logic.
    • Design token files: A collection of JSON or JS module files. The location of these files must be specified in the source attribute of your configuration file.

    Optional components:

    • Assets: A directory for managing non-token files (e.g., fonts, images) within the same package.
    - config.json
    - tokens
      - size
        - font.json
      - color
        - font.json
    - assets
      - fonts
      - images
  5. Migrate from CTI to Token Type in Version 4

    main

    Version 4 removes the heavy reliance on CTI (Category/Type/Item) structure. Instead of relying on attributes.category (often set via the attribute/cti transform), Style Dictionary now looks for a token.type property to determine token types. This aligns with the Design Tokens Community Group specification.

    Example Token Structure:

    {
      "color": {
        "red": {
          "value": "#FF0000",
          "type": "color"
        }
      }
    }

    Transform Changes:

    • Built-in name transforms are now reliant only on the token path and have been renamed from name/cti/[casing] to name/[casing]. (e.g., name/cti/kebab becomes name/kebab).
    • content/icon is renamed to html/icon.
    • font/[platform]/literal transforms are replaced by content/[platform]/literal (e.g., content/objC/literal).
  6. Use custom format helpers from style-dictionary/utils

    main

    Style Dictionary provides internal helper methods to simplify the creation of custom formats. These helpers are exported from the style-dictionary/utils entrypoint. Common helpers include fileHeader (to generate file headers based on file metadata) and formattedVariables (to generate formatted variable strings).

    import StyleDictionary from 'style-dictionary';
    import { fileHeader, formattedVariables } from 'style-dictionary/utils';
    import { propertyFormatNames } from 'style-dictionary/enums';
    
    StyleDictionary.registerFormat({
      name: 'myCustomFormat',
      format: async ({ dictionary, file, options }) => {
        const { outputReferences, sort } = options;
        const header = await fileHeader({ file });
        return (
          header +
          ':root {\n' +
          formattedVariables({
            format: propertyFormatNames.css,
            dictionary,
            outputReferences,
            sort, // SortOption - see types
          }) +
          '\n}\n'
        );
      },
    });
  7. Defer transitive transformations manually

    main

    Inside a transitive transform's transform function, you can defer the transformation to a later cycle of reference resolution by returning undefined. This is useful when the transformation depends on a property that is itself a reference and hasn't been resolved yet. Use the usesReferences utility from style-dictionary/utils to check if a property contains a reference.

    import { StyleDictionary } from 'style-dictionary';
    import { usesReferences } from 'style-dictionary/utils';
    
    StyleDictionary.registerTransform({
      name: 'my-deferred-transform',
      type: 'value',
      transitive: true,
      transform: (token) => {
        const darkenModifier = token.darken;
        if (usesReferences(darkenModifier)) {
          // defer this transform, because our darken value is a reference
          return undefined;
        }
        return darken(token.value, darkenModifier);
      },
    });
  8. Understand Token Matching in Style Dictionary v4+

    main

    From version 4 onwards, Style Dictionary determines a token's type using the token.type property or the $type property (for DTCG spec format). This replaces the version 3 CTI structure where type was determined via token.attributes.category.

    If you use a custom token structure that does not follow the standard CTI (Category, Type, Item) or DTCG formats, you must write custom transforms or ensure the proper attributes are present on your tokens.

  9. Import Style Dictionary using Package Entrypoints

    main

    Style Dictionary uses package entrypoints (export maps), which restricts imports to specific paths. Direct imports from internal file paths are no longer allowed and will fail in modern environments.

    Available entrypoints:

    • style-dictionary: The main module.
    • style-dictionary/utils: Utility functions like usesReferences and getReferences.
    • style-dictionary/fs: File system utilities (fs, setFs).
    • style-dictionary/types: TypeScript type definitions.

    Tooling Requirements:

    • TypeScript: Set moduleResolution to 'nodenext', 'node16', or 'bundler'.
    • Rollup: Requires @rollup/plugin-node-resolve.
    • Webpack: Version 5 or higher.
    • Vite: Version 3 or higher.
    import StyleDictionary from 'style-dictionary';
    import { usesReferences } from 'style-dictionary/utils';
    import { fs, setFs } from 'style-dictionary/fs';
    import type { DesignToken } from 'style-dictionary/types';
  10. Define design tokens using Style Dictionary or DTCG formats

    main

    Design tokens are the primary input for Style Dictionary. You can define them using the original Style Dictionary format or the Design Token Community Group (DTCG) spec.

    Important: In version 4 and later, you can use either format, but you cannot combine them within a single Style Dictionary instance.

    • Style Dictionary format: Uses value, type, and comment.
    • DTCG format: Uses $value, $type, and $description.

    A design token is identified as any node in your JSON object that contains a value (or $value) attribute.

    // Style Dictionary format
    {
      "colors": {
        "font": {
          "base": { "value": "#111111", "type": "color" }
        }
      }
    }
    
    // DTCG format
    {
      "colors": {
        "$type": "color",
        "font": {
          "base": { "$value": "#111111" }
        }
      }
    }
  11. Combine Transform Groups with standalone transforms

    main

    You can use both transformGroup and transforms within the same platform configuration. When doing so, the standalone transforms are applied after the transforms contained within the transformGroup.

    If you require a specific execution order that differs from this (where standalone transforms always follow the group), you should register a custom transform group instead of combining them.

    {
      "source": ["tokens/**/*.json"],
      "platforms": {
        "android": {
          "transformGroup": "android",
          "transforms": ["name/snake"]
        }
      }
    }