lukasoppermann / design-tokens

🎨 Figma plugin to export design tokens to json in an amazon style dictionary compatible format.
https://www.figma.com/community/plugin/888356646278934516/Design-Tokens
MIT License
953 stars 131 forks source link

Add support for variable references transformation #260

Open ryanzec opened 1 year ago

ryanzec commented 1 year ago

Right now if you reference one variable in another variable, you can not properly transform those design token as style dictionary will error with error like this:

Reference doesn't exist: button.mode-1.space.icon.value tries to reference space.small3, which is not defined

This seems to be be because when parse the variable alias, the mode is not being added to the values so the reference does not exist.

This seems like a pretty code feature to support and think this plugin should support it.

This is a big enough issue for me that I added support for it myself and will open up a PR shortly.

ryanzec commented 1 year ago

PR added

lukasoppermann commented 1 year ago

Hey, referencing modes in references does not really make sense in my mind, as you would normally set modes outside and load the mode specific files only. However I just published an option to disable modes, which only works if you have only one mode. Does this solve your issue already?

ryanzec commented 1 year ago

@lukasoppermann Disabling modes would not fix my issue as I specifically need to account for all the modes.

as you would normally set modes outside and load the mode specific files only

I am not sure what you mean here, lets you show you why supporting modes is a hard requirement for me.

Here is an examples of a collection of variables with multiple modes (there is a lot more variables here but the structure is what is important): Screen Shot 2023-08-14 at 6 58 04 AM

Here is an example of another collection that is using these colors collection variables: Screen Shot 2023-08-14 at 7 00 11 AM

Now if we just look at the background color, it shows a white-ish since it show the default mode value (which is light) but for dark is would be a black-ish color.

Here is a component built with those variables along with its structure: Screen Shot 2023-08-14 at 7 03 48 AM

With this setup I am able to create one version of the component and then to get the dark mode, I create an instance of that component and set the mode for colors to dark in the wrapping frame.

Now in order to be able to export tokens that will give me both modes of all the colors, I basically need to do what I did in my PR because as it stands now, exporting these variables won't even transform and maybe the removing of the mode you mentioned might make it transform but it only give one mode meaning I would need to manually create the css variables for the other modes which seem counter to what you are supposed to be able to do with design tokens. Am I missing something?

If this is something you don't think needs to be supported, thats fine, I will just maintain my fork of this library and publish it myself as without some level of mode support, this tool does not seem useable for me.

ryanzec commented 1 year ago

@lukasoppermann Does my use case make sense or am i missing something about the use of variables in Figma?

lukasoppermann commented 1 year ago

Yes, this is one use case that makes sense.

However, a more common case is that you would have two css files:

and in those you want to have the same variable names, e.g. --surface-pure. This way you load light.css or dark.css depending on the mode the user has selected and don't have to reference different variables.

The ideal solution would be to export one file per mode for each variable collection and one file for the other tokens.

ryanzec commented 1 year ago

That is exactly what I am doing but in order to create those 2 files, I need all modes to be accounted for and since in Figma, I can and am aliasing variables that have multiple modes, I need those variables to account for the modes. I could just not use variables aliasing but there is a reason that feature is available and would like to be able to use it.

I am trying to understand the downside of this change. Right now, if you reference a variable with another one, by default, attempting to transform those tokens will straight error out and not transform. If you disable mode referencing that was recently added, it will transform those however it will only transform for one mode (it seems like the last mode since it seem to just overwrite an previous mode since without referencing the mode, the name of variables with mode all become the same) broken because it is missing a bunch of variable. At least with this change, all variables and modes are being exported to tokens and creating the 2 (or how every many you want) css files is possible without too much extra work in the transformation code.

Are you suggesting that the plugin should export multi design token files? While I guess that could work, that seems like a whole lot harder to do both in the plugin (not even sure if the plugin system allows multiple file generation with a single action) and then in the transformation code and I don't see any benefit for all that extra work (I assume I am missing something).

If you feel this solution I came up with is not a good one, that is fine, just let me know so I can fork this plugin to create my own version that has some level of multi-mode support as with how the plugin function today, it does not work with my workflow (unless you can provide a reason why this solution is not as good as any other solution).

yinonov commented 1 year ago

let's consider the desired result in the web. In a practical sense I would expect to have multiple files for theming light.css and dark.css

and those would contain color scheme variable respectively e.g.

:root {
  --color-primary: #1b8e2f;
}

Rest of the tokens should always refer to the same token above (variable names don't differ between themes in the semantic level of tokens). Tokens for a component (e.g. button) will output the following

.button {
  --background-color: var(--color-primary); 
}

in practice, following the architecture above in Figma's variables, the plugin (when set to enable mode referencing) will output redundant structure for the individual components. the result would be

{
  "color": {
    "light": {
      "primary": "darkgreen"
    },
    "dark": {
      "primary": "lightgreen"
    }
  },
  "button": {
    "mode-1": {
      "background-color": {
        "value": "{color.primary}"
      }
    }
  },
  "dark": {
    "mode-1": {
      "background-color": {
        "value": "{color.primary}"
      }
    }
  }
}

instead of the desired

light.tokens.json

{
  "color": {
    "primary": "darkgreen"
  }
}

dark.tokens.json

{
  "color": {
    "primary": "lightgreen"
  }
}

components.tokens.json

{
  "button": {
    "background-color": {
      "value": "{color.primary}"
    }
  }
}

could the plugin support extracting modes into multiple files?

lukasoppermann commented 1 year ago

I'd love this. In an ideal world we would get one file for old tokens and one file per collection+mode combination for variables.

I am not sure if this is technically possible (downloading/writing multiple files)

If you can find this out and send a PR that would be awesome. 👍

yinonov commented 1 year ago

I can try. Have you experienced any challenges/blockers on that? Any insights from previous attempts? Or would this be the first initiative

KodinManiac commented 11 months ago

Hey @lukasoppermann I ran into this issue which is caused because my UX team uses multiple variable modes in the Figma design, variable references exported in the design token are broken due to the variable modes not being added in the reference. are there any plans to support this in the near future or any work arounds for now?

I am trying not to add some custom codes to style dictionary