A utility that mutates and transforms a style-dictionary object into something Figma Tokens plugin understands

Overview

style dictionary playground logo

Brought to you by
‹div›RIOTS ‹div›RIOTS

Style Dictionary To Figma

A utility that transforms a style-dictionary object into something Figma Tokens plugin understands.

Used by Design Systems in Backlight using design tokens in style-dictionary that can be synced into Figma via the Figma Tokens plugin.

Features

  • Allows marking a category as a custom tokenset so that it will appear as a separate tokenset in Figma. This is useful if you want to combine many base tokens into a "global" set for example.
  • Trims .value from reference values as Figma Tokens plugin does not use this suffix.
  • Trims the name properties from tokens since Figma Tokens plugin uses this property to name its tokens, however, without a name property it creates its own naming/nesting by the object structure which is way nicer.
  • Use the reference values rather than its resolved values

Usage

npm i @divriots/style-dictionary-to-figma
import styleDictionaryToFigma from '@divriots/style-dictionary-to-figma';

const sdObject = { ... };
const figmaObj = styleDictionaryToFigma(sdObject);

In case you want its separate counterparts, you can import them separately.

import {
  trimValue,
  trimName,
  useRefValue,
  markTokenset,
} from '@divriots/style-dictionary-to-figma';

Once you transformed the object to Figma, a recommendation is to push this to GitHub and use the Figma Tokens plugin to sync with it to use the tokens in Figma.

Use in Backlight / Style-dictionary

Simply import the styleDictionaryToFigma utility and create a style-dictionary formatter:

import styleDictionaryToFigma from '@divriots/style-dictionary-to-figma';

export default {
  source: ['**/*.tokens.json'],
  format: {
    figmaTokensPluginJson: opts => {
      const { dictionary } = opts;
      const parsedTokens = styleDictionaryToFigma(dictionary.tokens);
      return JSON.stringify(parsedTokens, null, 2);
    },
  },
  platforms: {
    json: {
      transformGroup: 'js',
      buildPath: '/tokens/',
      files: [
        {
          destination: 'tokens.json',
          format: 'figmaTokensPluginJson',
        },
      ],
    },
  },
};

This spits out a file /tokens/tokens.json which Figma Tokens plugin can import (e.g. through GitHub).

Since Backlight has GitHub and Style-Dictionary integration out of the box, this process is very simple.

Comments
  • Clarification on how the markTokenset feature works

    Clarification on how the markTokenset feature works

    In the README, it says that:

    Allows marking a category as a custom tokenset so that it will appear as a separate tokenset in Figma. This is useful if you want to combine many base tokens into a "global" set for example.

    This is exactly what I want to do. However, it seems like Figma Tokens might not support this anymore? E,g, in Figma Tokens, it seems that every tokenset is a separate JSON, and markTokenset in the same JSON does not have any effect.

    I might be doing something wrong, so looking for clarification whether this is supposed to work or not. Thanks!

    documentation external 
    opened by mihkeleidast 12
  • Warning: While building tokens.json, token collisions were found; output may be unexpected.

    Warning: While building tokens.json, token collisions were found; output may be unexpected.

    I stumble on what seems to be a false positive warning. Let's say I have this style dictionary config:

    const { transform } = require("@divriots/style-dictionary-to-figma");
    
    module.exports = {
      source: ["tokens/**/*.js"],
      format: {
        figmaTokensPlugin: ({ dictionary }) => {
          const transformedTokens = transform(dictionary.tokens, {
            cleanMeta: true,
          });
          return JSON.stringify(transformedTokens, null, 2);
        },
      },
      platforms: {
        css: {
          transformGroup: "css",
          buildPath: "css/",
          files: [
            {
              destination: "variables.css",
              format: "css/variables",
            },
          ],
          prefix: "qa",
        },
        figma: {
          buildPath: "figma/",
          files: [
            {
              destination: "tokens.json",
              format: "figmaTokensPlugin",
            },
          ],
        },
      },
    };
    
    

    In my tokens folder, I have:

    // radii.js
    function radius(num) {
        return {
          value: `${num}px`,
          type: "borderRadius",
        };
      }
      
      module.exports = {
        radius: {
          xxsmall: radius(1),
          xsmall: radius(2),
          small: radius(4),
          medium: radius(8),
          large: radius(12),
          xlarge: radius(16),
          xxlarge: radius(32),
        },
      };
    
    // spacings.js
    function spacing(num) {
      return {
        value: `${num}px`,
        type: "spacing",
      };
    }
    
    module.exports = {
      spacing: {
        xxxsmall: spacing(4),
        xxsmall: spacing(8),
        xsmall: spacing(12),
        small: spacing(16),
        medium: spacing(24),
        large: spacing(32),
        xlarge: spacing(40),
        xxlarge: spacing(48),
        xxxlarge: spacing(64),
      },
    };
    

    Running style dictionary:

    > style-dictionary build --config style-dict.config.js
    
    
    css
    ✔︎ css/variables.css
    
    figma
    ⚠️ figma/tokens.json
    While building tokens.json, token collisions were found; output may be unexpected.
        Output name xxsmall was generated by:
            radius.xxsmall   1px
            spacing.xxsmall   8px
        Output name xsmall was generated by:
            radius.xsmall   2px
            spacing.xsmall   12px
        Output name small was generated by:
            radius.small   4px
            spacing.small   16px
        Output name medium was generated by:
            radius.medium   8px
            spacing.medium   24px
        Output name large was generated by:
            radius.large   12px
            spacing.large   32px
        Output name xlarge was generated by:
            radius.xlarge   16px
            spacing.xlarge   40px
        Output name xxlarge was generated by:
            radius.xxlarge   32px
            spacing.xxlarge   48px
    This many-to-one issue is usually caused by some combination of:
        * conflicting or similar paths/names in property definitions
        * platform transforms/transformGroups affecting names, especially when removing specificity
        * overly inclusive file filters
    

    My understanding is that there should not be name collisions, since the paths are different (e.g. radius.medium vs spacing.medium). Moreover, CSS transform don't generate these warnings. Did I miss something, or is it a bug?

    [email protected] and @divriots/[email protected]

    external 
    opened by jsamr 3
  • Tailwind CSS → Style Dictionary → Figma Tokens

    Tailwind CSS → Style Dictionary → Figma Tokens

    Thank you for this, @divriots. Seeing that green ✔ in the terminal feels good (as a designer) 🙇‍♂️

    Intention So my setup was I wanted to pull tailwindcss default --full config into Design Tokens so for anything that is vanilla/default tailwind, I can apply them in my design. For example, I want to apply an equivalent of space-x-4 or gap-4 via Figma Tokens (which is 1rem) on my Figma, so it's consistent with tailwindcss when developers use that specific class.

    However, after transforming from SD to JSON I noticed some tokens were not “categorized” in the format that Figma Tokens utilize. I am sure this isn‘t a bug of style-dictionary-to-figma but more a specific transformer code I need to figure out to fix this: CleanShot 2022-09-13 at 22 58 22@2x

    I would appreciate any pointers that can help me find progress in the right direction. I understand if this is out of scope, but I want to thank you again for making a designer like myself feel this is solvable. Here‘s what I got so far: https://github.com/ajmalafif/tailwind-to-style-dictionary/blob/sd-to-figma/style-dictionary.config.js

    opened by ajmalafif 3
  • fix: keep array values as arrays

    fix: keep array values as arrays

    The previous object fix almost got my exporting code working, but not just yet. The description and tests are quite real, e.g. Figma Tokens accepts multiple shadows in a single boxShadow token, and stores them as arrays.

    opened by mihkeleidast 3
  • Fix trimValue when value is object

    Fix trimValue when value is object

    In style-dictionary, values can be objects (see https://github.com/amzn/style-dictionary/pull/623 for the implementation there). The current trimValue implementation here expects them to always be strings, and throws when it encounters an object.

    opened by mihkeleidast 3
  • Allow useRefValue on some tokens, but not on others

    Allow useRefValue on some tokens, but not on others

    I'm trying to work around this Figma Tokens issue: https://github.com/six7/figma-tokens/issues/706

    Our shadow tokens are defined as follows:

    {
      "shadow": {
        "core": {
          "2": {
            "value": {
              "x": "0",
              "y": "1",
              "blur": "2",
              "spread": "0",
              "color": "{color.core.black.8}",
              "type": "dropShadow"
            }
          },
          "4": {
            "value": {
              "x": "0",
              "y": "2",
              "blur": "4",
              "spread": "0",
              "color": "{color.core.black.8}",
              "type": "dropShadow"
            }
          },
          "8": {
            "value": {
              "x": "0",
              "y": "4",
              "blur": "8",
              "spread": "0",
              "color": "{color.core.black.8}",
              "type": "dropShadow"
            }
          }
        },
        "elevation": {
          "small": {
            "value": ["{shadow.core.4}", "{shadow.core.2}"]
          },
          "medium": {
            "value": ["{shadow.core.8}", "{shadow.core.2}"]
          }
        }
      }
    }
    

    Our elevation shadows stack the different core shadows and we'd like to not have to duplicate those definitions. We would like to use useRefValue, so the token relationships would be visible in Figma Tokens as well. This is impossible currently due to how our tokens are defined and the FT issue I linked above.

    Is there an easy way of adding some sort of filtering to useRefValue, so that the specific shadow.elevation.small.value would not use references, but everything else still would?

    opened by mihkeleidast 2
  • default export is not correct

    default export is not correct

    Hello!

    I tried importing the code in this way:

    const styleDictionaryToFigma = require('@divriots/style-dictionary-to-figma');

    But, found that it doesn't work. Needed to add .default.

    const styleDictionaryToFigma = require('@divriots/style-dictionary-to-figma').default;

    Also may I suggest you change the README to use the registerTransform method on StyleDictionary:

    StyleDictionaryPackage.registerFormat({
      name: 'figmaTokensPlugin',
      formatter({ dictionary }) {
        const parsedTokens = styleDictionaryToFigma(dictionary.tokens);
        return JSON.stringify(parsedTokens, null, 2);
      }
    });
    

    Thanks!

    opened by dmackerman 2
  • fix: use ref value to only target and restore reference values

    fix: use ref value to only target and restore reference values

    also fixes the high prio vulnerability, for the moderate one it seems quite new and no fix yet.

    fixes https://github.com/divriots/style-dictionary-to-figma/issues/20

    @mihkeleidast this should fix your issue I think

    opened by jorenbroekema 1
  • Currently doesn't seem to work with aliased values

    Currently doesn't seem to work with aliased values

    Any ideas on why this doesn't work? Sorry if I'm overlooking something simple or that is already documented.

    /alias
    -- color.alias.json5
    /foundation
    -- color.json5
    

    color.alias.json5

    {
      color: {
        brand: {
          blue: {
            '10': {
              value: '#DBF0FF',
              category: 'alias',
            },
          },
        },
      },
    }
    
    

    color.json5

    {
      color: {
        blue: {
          '10': {
            value: '{color.brand.blue.10.value}',
            category: 'color',
            type: 'color',
            attributes: {
              category: 'color',
            },
          },
        },
      },
    }
    

    Output:

    {
      color: {
        blue: {
          '10': {
            value: '{color.brand.blue.10}',
            category: 'color',
            type: 'color',
            attributes: {
              category: 'color',
              type: 'blue',
              item: '10',
            },
            filePath: '../brand/src/lib/foundation/color.json5',
            isSource: true,
            original: {
              value: '{color.brand.blue.10}',
              category: 'color',
              type: 'color',
              attributes: {
                category: 'color',
              },
            },
            path: {
              '0': 'color',
              '1': 'blue',
              '2': '10',
            },
          },
        },
      },
    }
    
    opened by jclarkcisco 1
  • Version Packages

    Version Packages

    This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

    Releases

    @divriots/[email protected]

    Minor Changes

    • ab01a1e: BREAKING: if an upper token group does not have a tokenset property, it will get placed in a "global" tokenset by default. This means that no action is required by the user of the transformer to get a working JSON for Figma Tokens Plugin, but this change is potentially breaking because of how it changes the JSON output.

      Before

      {
        "core": {
          "color": {
            "primary": {
              "base": {
                "type": "color",
                "value": "#14b8a6"
              },
              "secondary": {
                "type": "color",
                "value": "#ff0000"
              }
            }
          }
        }
      }
      

      Nothing is changed in the output. However, if you have references, they might be broken because the plugin will interpret this as "color" being the upper property in a tokenset called "core".

      After

      {
        "core": {
          "color": {
            "primary": {
              "base": {
                "type": "color",
                "value": "#14b8a6"
              },
              "secondary": {
                "type": "color",
                "value": "#ff0000"
              }
            }
          }
        }
      }
      

      turns into

      {
        "global": {
          "core": {
            "color": {
              "primary": {
                "base": {
                  "type": "color",
                  "value": "#14b8a6"
                },
                "secondary": {
                  "type": "color",
                  "value": "#ff0000"
                }
              }
            }
          }
        }
      }
      

      Your reference, for example {core.color.primary.base} will now work properly because "core" is not interpreted as the tokenset, "global" is.

    Patch Changes

    • ab01a1e: Fix clean-meta utility by using a proper isObject check which excludes arrays (values can be arrays).
    opened by github-actions[bot] 0
  • Version Packages

    Version Packages

    This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

    Releases

    @divriots/[email protected]

    Patch Changes

    • 2c9be59: Allow tokensets to be the same name as the upper most keys in the tokens object, e.g.:

      {
        "core": {
          "tokenset": "core",
          "color": {
            "value": "#ff0000",
            "type": "color"
          }
        }
      }
      

      will become

      {
        "core": {
          "core": {
            "color": {
              "value": "#ff0000",
              "type": "color"
            }
          }
        }
      }
      

      so that Figma Tokens plugin picks it up properly.

    opened by github-actions[bot] 0
  • How to turn off the global?

    How to turn off the global?

    Hi! I have a problem, it used to work properly. Updated package configuration to 4 versions and in vain. These files are automtaically assigned to the global group that prevents me from working. There is no time to convert json files. So that’s how to turn off this automatic function of inserting the global group?

    UPD: Solved the issue of setting in config file) Excuse me

    opened by AndySobol 1
Releases(v0.4.0)
  • v0.4.0(Sep 15, 2022)

    Minor Changes

    • ab01a1e: BREAKING: if an upper token group does not have a tokenset property, it will get placed in a "global" tokenset by default. This means that no action is required by the user of the transformer to get a working JSON for Figma Tokens Plugin, but this change is potentially breaking because of how it changes the JSON output.

      Before

      {
        "core": {
          "color": {
            "primary": {
              "base": {
                "type": "color",
                "value": "#14b8a6"
              },
              "secondary": {
                "type": "color",
                "value": "#ff0000"
              }
            }
          }
        }
      }
      

      Nothing is changed in the output. However, if you have references, they might be broken because the plugin will interpret this as "color" being the upper property in a tokenset called "core".

      After

      {
        "core": {
          "color": {
            "primary": {
              "base": {
                "type": "color",
                "value": "#14b8a6"
              },
              "secondary": {
                "type": "color",
                "value": "#ff0000"
              }
            }
          }
        }
      }
      

      turns into

      {
        "global": {
          "core": {
            "color": {
              "primary": {
                "base": {
                  "type": "color",
                  "value": "#14b8a6"
                },
                "secondary": {
                  "type": "color",
                  "value": "#ff0000"
                }
              }
            }
          }
        }
      }
      

      Your reference, for example {core.color.primary.base} will now work properly because "core" is not interpreted as the tokenset, "global" is.

    Patch Changes

    • ab01a1e: Fix clean-meta utility by using a proper isObject check which excludes arrays (values can be arrays).
    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Sep 14, 2022)

    Patch Changes

    • 2c9be59: Allow tokensets to be the same name as the upper most keys in the tokens object, e.g.:

      {
        "core": {
          "tokenset": "core",
          "color": {
            "value": "#ff0000",
            "type": "color"
          }
        }
      }
      

      will become

      {
        "core": {
          "core": {
            "color": {
              "value": "#ff0000",
              "type": "color"
            }
          }
        }
      }
      

      so that Figma Tokens plugin picks it up properly.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Sep 12, 2022)

    Patch Changes

    • f9cf466: Allow passing an options object, for example cleanMeta, to clean unwanted meta props from the style-dictionary object.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Sep 9, 2022)

    Patch Changes

    • 1c0ee01: Do proper isObject check (typeof null and Array are also 'object') where needed. Fixes bug with metadata props with type Array getting altered by trimValue to become Objects.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jul 20, 2022)

    Minor Changes

    • b6cb742: BREAKING: do not restore original value if it was not a reference value. Before, it used to always restore, which unintentionally also restored style-dictionary transforms. For nested values, restore fully if any reference is found inside the nested value (object or array). If undesired, you can always use ignoreUseRefValue (see README) to fall back to keeping the fully resolved value. Currently, a hybrid solution that restores only the subparts of a value that is partially using references, is not available. Feel free to raise an issue if needed to explain your use case.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Jul 14, 2022)

    Patch Changes

    • c30d4c1: Allow passing ignoreUseRefValue boolean metadata as a sibling to the token value property. It will use the resolved value rather than using the original reference value after conversion when this is set to true.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(May 6, 2022)

    Minor Changes

    • 00c39e3: BREAKING: no longer using default export, this is considered an anti-pattern for JS libraries. Re-export wildstars with default exports in ESM is one example quirk, another example is CommonJS not supporting default exports next to named exports in a single file. Now, the main export is a named export called "transform" and you have to import it as such.

      Before:

      // ESM
      import styleDictionaryToFigma from '@divriots/style-dictionary-to-figma';
      // CommonJS
      const styleDictionaryToFigma = require('@divriots/style-dictionary-to-figma');
      
      styleDictionaryToFigma({...}) // figma object
      

      After:

      // ESM
      import { transform } from '@divriots/style-dictionary-to-figma';
      // CommonJS
      const { transform } = require('@divriots/style-dictionary-to-figma');
      
      transform({...}) // figma object
      
    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(May 3, 2022)

    Patch Changes

    • ff5d591: Keeps an array-type value as an array. This is useful with boxShadows that can have multiple stacked shadows in a single token.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.2(May 2, 2022)

  • v0.1.1(Mar 3, 2022)

    Patch Changes

    • 52117f8: Add CommonJS entrypoint, allowing importing with const sdToFigma = require('@divriots/style-dictionary-to-figma').default.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Feb 10, 2022)

Owner
‹div›RIOTS
Frontend is back!
‹div›RIOTS
Base62-token.js - Generate & Verify GitHub-style & npm-style Base62 Tokens

base62-token.js Generate & Verify GitHub-style & npm-style Secure Base62 Tokens Works in Vanilla JS (Browsers), Node.js, and Webpack. Online Demo See

Root 4 Jun 11, 2022
A little toy app to help you find the nearest match for a given color within a Figma Tokens color palette.

Hey Palette So you've got a color palette in Figma and you've used the Figma Tokens plugin to export that palette to JSON. Let's say you have a color

Kalo Pilato 5 Nov 15, 2022
A utility for creating toggleable items with JavaScript. Inspired by bootstrap's toggle utility. Implemented in vanillaJS in a functional style.

LUX TOGGLE Demo: https://jesschampion.github.io/lux-toggle/ A utility for creating toggleable dom elements with JavaScript. Inspired by bootstrap's to

Jess Champion 2 Oct 3, 2020
VanillaSelectBox - A dropdown menu with lots of features that takes a select tag and transforms it into a single or multi-select menu with 1 or 2 levels

vanillaSelectBox v1.0.0 vanillaSelectBox : v1.00 : Adding a package.json file New : Possibility to change the dropdown tree and change the remote sear

philippe MEYER 103 Dec 16, 2022
Receive crypto payments from anywhere around the world, options including native tokens (MATIC, ETHER,BUSD), Tokens (USDT,BUSD), NFTs and more.

Receive payments for service rendered in crypto using different options. Go borderless with bonpay, gain access to varities of crypto assets, safe and

Johnson awah Alfred 6 Nov 11, 2022
A PostCSS plugin that transforms `css var` to `less var`.

PostCSS CSS var to Less var A PostCSS plugin to convert CSS variables to Less variables Installation npm install postcss-transform-css-var Examples /

cherry-man 9 Nov 28, 2022
A dead-simple Bookmarklet and Chrome Extension implementation of something like Bionic Reading

What is it? Inspired by Bionic Reading, this Bookmarklet modifies a webpage to display the first half of each word in bold. Can also be installed as a

null 35 Dec 5, 2022
For some realizations of the title and thinking of the book Introduction to Algorithms, if there is something wrong, please correct me.

Introduction-to-Algorithms Introduce Origin of this library Some implementations of the topics in Introduction to Algorithms and some reflections on t

biao 2 Jun 9, 2022
Chrome Extensions are something which we use very frequently in our day-to-day life for example Grammarly

Chrome-Extension Chrome Extensions are something which we use very frequently in our day-to-day life for example Grammarly, In this project similarly,

Harshita sharma 97 Dec 14, 2022
A custom select dropdown. This is something that is not too difficult to make.

Custom-Dropdown-JS A custom select dropdown using basic JS fucntionality. This is something that is not too difficult to make. But it shows that you h

Devanshu Vashishtha 2 Mar 26, 2022
Write something on your contribution graph!

GitWrite Write something on your contribution graph! What is GitWrite? GitWrite is a little tool I developed that lets you add a short message to a ye

yodalightsabr 23 Sep 19, 2022
Types generator will help user to create TS types from JSON. Just paste your single object JSON the Types generator will auto-generate the interfaces for you. You can give a name for the root object

Types generator Types generator is a utility tool that will help User to create TS Interfaces from JSON. All you have to do is paste your single objec

Vineeth.TR 16 Dec 6, 2022
A meme generator plugin for Figma and FigJam. Import memes from all over the internet with customizable captions and share it far and wide.

Is This A Meme? ???? ?? A meme generator plugin for Figma and FigJam. Import memes from all over the internet, add your captions, and share it far and

Aashrey Sharma 6 Aug 30, 2022
A library for panning and zooming elements using CSS transforms :mag:

Panzoom Examples Panzoom is a small library (~3.7kb gzipped) to add panning and zooming functionality to an element. Rather than using absolute positi

Timmy Willison 1.8k Dec 26, 2022
Customise this Figma plugin template for your own design team.

Design Toolkit Customise this Figma reference plugin to provide useful resources and automations for yourself or your team. Inspect the code to see ho

Josh Harwood 10 Jul 7, 2022
🪆 Template intended to serve as a starting point if you want to bootstrap a Figma Plugin in TypeScript.

?? Codely Figma Plugin Skeleton Template intended to serve as a starting point if you want to bootstrap a Figma Plugin in TypeScript. Take a look, pla

CodelyTV 26 Dec 22, 2022
A typescript transform that converts exported const enums into object literal.

ts-transformer-optimize-const-enum A typescript transformer that convert exported const enum into object literal. This is just like the one from @babe

Fonger 22 Jul 27, 2022
Project Cider. A new look into listening and enjoying Apple Music in style and performance. 🚀

Links Wiki Request Feature Report Bug View The Releases Install Sources Compiling and Configuration For more information surrounding configuration, co

Cider Collective 5.8k Jan 5, 2023
🐌 让 Figma 网络访问速度更快

FigmaNetOK 让 Figma 网络速度访问速度更快的方法(尤其是在 ???? 中国) 不使用翻墙 更改本地 Hosts 配置 Figma 有不同的服务器,通常你的系统会自动选择 Figma 的服务地址,有些时候因为运营商、Figma 服务状态、DNS 设置等等原因,自动选择的 Figma 服

null 138 Dec 28, 2022