amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.93k stars 557 forks source link

Question: Convert color using registerTransform that uses a custom category #916

Open djmtype opened 1 year ago

djmtype commented 1 year ago

I already looked at the advanced example, but still have no clue to transform colors provided as to hex to hsl4. I can't used the built-in color/hsl-4 transformGroup because this project's category is referenced as colors instead of color.

JSON example:

"colors": {
    "black": {
      "value": "#000000",
      "type": "color"
    }
}

Currently:

StyleDictionary.registerTransform({
  name: 'colorHsl', 
  type: 'value',
  matcher: (token) =>  ["color"].includes(token.type),
  transformer: (token) =>  // what goes here? token.value.?
});
StyleDictionary.registerTransformGroup({
    name: "css",
    transforms: ["colorHsl"]
})
nahiyankhan commented 1 year ago

Howdy. I can think of two options.

Option 1 You could leave everything as is and instead create a custom attribute/cti to remap colors to color as the category. Then the default transforms that use the isColor matcher should work out.

StyleDictionary.registerTransform({
  name: 'attribute/cti', 
  type: 'attribute',
    transformer: function(token) {

      const attrNames = ['category', 'type', 'item', 'subitem', 'state'];
      const originalAttrs = token.attributes || {};
      const generatedAttrs =  {}

      for(let i=0; i<token.path.length && i<attrNames.length; i++) {
        let attr = token.path[i];
        if (attr === "colors") { attr = "color" };
        generatedAttrs[attrNames[i]] = attr;
      }

      return Object.assign(generatedAttrs, originalAttrs);
    }
});

Option 2

Register a custom transform as you started. Note: StyleDictionary uses tinycolor2 for its color transformations. You would have to import it as well. But you could use whichever else you prefer. This option means, you don't have to mess with the default attributes setting but it also does mean anything else you are doing with colors, you likely have to define custom transforms just for the matcher.

var Color = require('tinycolor2');

StyleDictionary.registerTransform({
  name: 'color/hsl', 
  type: 'value',
  matcher: (token) =>  token.attributes.category === "colors",
  transformer: (token) =>  {
      return Color(token.value).toHslString();
});

And then the transformGroup. color/css switched to the custom color/hsl.

StyleDictionary.registerTransformGroup({
    name: "css",
    transforms: [
      'attribute/cti',
      'name/cti/kebab',
      'time/seconds',
      'content/icon',
      'size/rem',
      'color/hsl'
    ]
})

Let me know if this makes sense and works for you. Apologies if there's an error (didn't setup and run them).

djmtype commented 1 year ago

Much appreciated @nahiyankhan. Thank you!