amzn / style-dictionary

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

Predefined Transform for Gradients in color/css #995

Closed dbaitech closed 4 months ago

dbaitech commented 1 year ago

I would like to see an added feature to the color/css predefined transform that allows the "value" key to have a string containing a css gradient. For example, I am currently trying to add a linear gradient to a list of backgroundColors in the "color" section which looks like this:

"promo gradient": {
                "backgroundColor": {
                    "value": "linear-gradient(135deg, #52a1dd 20.0%, #a60054 88.00%)"
                }
 }

However, when Style Dictionary converts it into CSS tokens, it is not being transformed and simply results in the value #000000.

Since gradients are an important part of color styling, it would be great to see this feature added.

dbaitech commented 1 year ago

A workaround I'm using is to create a registeredTransform that overrides the color/css transform by adding a feature that identifies when the string value contains "gradient" so that it just returns the string itself. Otherwise, it works the same as color/css.

// Add custom transform to override color/css predefined transform
  //  Works the same as color/css but also includes linear-gradient
  StyleDictionary.registerTransform({
    name: "color/css",
    type: "value",
    matcher: (token) => token.attributes.category === "color",
    transformer: (token) => {
      if (token.value.includes("gradient")) {
        return `${token.value}`;
      }

      // if color is not fully opaque, then write as RGBA to include opacity
      if (
        token.value.includes("transparent") ||
        /rgba\(.*[^1]\)/.test(token.value) // checks if opacity is not 1
      ) {
        return Color(token.value).toRgbString();
      }

      return Color(token.value).toHexString();
    },
  });
Rykus0 commented 5 months ago

I think it would be a better global solution to update the matcher instead of changing the transform, since we effectively want to skip transforming the gradient the same as a straight color. Thoughts?

jorenbroekema commented 5 months ago

I agree, PRs welcome to update the matcher function: https://github.com/amzn/style-dictionary/blob/v4/lib/common/transforms.js#L40

When this returns false for colors in formats such as linear-gradient or similar, none of the color conversion transforms will be applied and you're free to use your own custom transform to transform it as you need (for CSS, probably no transform needed since it supports this format out of the box).

My suggestion, since all of the color transforms are using tinycolor2 would be to use: token.type === 'color' && Color(token.$value ?? token.value).isValid() check for the isColor matcher. Please add a test for this as well, probably here: https://github.com/amzn/style-dictionary/blob/v4/__tests__/transform/transformToken.test.js

Rykus0 commented 4 months ago

FYI - I'm working on this, just need to finish up tests.

Rykus0 commented 4 months ago

~Having a problem with the precommit hook; prettier keeps listing my file as different. If I run the formatter it seems to be applying whitespace changes to a bunch of files. Even after I add the changes for my file, the precommit hook is flagging it as changed and not committing it. Could it be because I'm on Windows?~

Figured it out. Had to apply the formatter changes without saving again in my editor.

jorenbroekema commented 4 months ago

Hey, you'll probably want to set your git global config core.autocrlf setting to either 'auto' or 'input', windows uses different characters for line endings.

jorenbroekema commented 4 months ago

Fix will be released in prerelease.28, I expect somewhere next week, thanks for raising the issue and contributing a fix folks, much appreciated!