Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: make 'ts/color/modifiers' use references by using CSS color functions #198

Open
1 task
thomasmattheussen opened this issue Sep 20, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@thomasmattheussen
Copy link
Contributor

What feature would you like?

color-mix is now supported in all major browsers. It would be cool if ts/color/modifiers makes use of this so it's still able to reference variables.

For example, take the following case

{
  "my-token": {
    "value": "{my-referenced-token}",
    "type": "color",
    "$extensions": {
      "studio.tokens": {
        "modify": {
          "type": "mix",
          "value": "{my-referenced-modifier}",
          "space": "srgb",
          "color": "{my-referenced-mix-token} "
        }
      }
    }
  },
  "my-referenced-modifier": {
    "value": 0.24,
    "type": "number"
  },
  "my-referenced-mix-token": {
    "value": "#000",
    "type": "color"
  },
  "my-referenced-token": {
    "value": "#FF00F8",
    "type": "color"
  }
}

This now outputs:

:root {
  --sdMyToken: rgb(73.8% 10.9% 71.6%);
  --sdMyReferencedModifier: 0.24;
  --sdMyReferencedMixToken: #000;
  --sdMyReferencedToken: #FF00F8;
}

but by using color-mix it could output

:root {
  --sdMyReferencedModifier: 0.24;
  --sdMyReferencedMixToken: #000;
  --sdMyReferencedToken: #FF00F8;
  --sdMyToken: color-mix(in srgb, var(--sdMyReferencedToken), var(--sdMyReferencedMixToken) var(--sdMyReferencedModifier));
}

Which then gives you the ability to modify those references separately, giving you more flexibility in subtheming and darkmode etc...

Would you be available to contribute this feature?

  • Yes, I would like to contribute this
@jorenbroekema
Copy link
Member

jorenbroekema commented Dec 8, 2023

For some context I'd like to add these two examples that showcase the difference between stacking the transitive transforms of color modifiers and not stacking them:

Why is this relevant?

Because when you would replace the modifier with color-mix, it means you'd get nested color-mix() calls for the stacking example, similar to how if you created a transitive transform that wraps math statements in calc(), you get nested calc() statements (even though that's redundant in this example, it is not redundant when we talk about nested color-mix calls).

{
  "colors": {
    "red": {
      "100": {
        "value": "{colors.red.500}",
        "type": "color",
        "$extensions": {
          "studio.tokens": {
            "modify": {
              "type": "lighten",
              "value": "0.4",
              "space": "hsl"
            }
          }
        }
      }
    }
  }
}

Non stacking:

:root {
  --sdColorsRed100: color-mix(in srgb, var(--sdColorsRed500), #fff 40%);
}

we're assuming for a second that outputReferences does not undo the work of color modifier transform, although it does, I'll address that later...

{
  "colors": {
    "red": {
      "100": {
        "value": "{colors.red.200}",
        "type": "color",
        "$extensions": {
          "studio.tokens": {
            "modify": {
              "type": "lighten",
              "value": "0.1",
              "space": "hsl"
            }
          }
        }
      }
    }
  }
}

Assuming the above, and assuming 200 refers to 300, etc. with the same lighten 0.1, stacking up

Stacking (without outputReferences):

:root {
  --sdColorsRed100: 
    color-mix(in srgb,
      color-mix(in srgb,
        color-mix(in srgb,
          color-mix(in srgb, #f00, #fff 10%) ,
        #fff 10%),
      #fff 10%),
    #fff 10%);
}

I did some testing and the above seems to work in CSS :) so that's good!

Finally, stacking without outputReferences:

:root {
  --sdColorsRed100: var(--sdColorsRed200); 
}

And now we get back to the topic of that outputReferences is undoing the work of the transform: all this work of transitively wrapping in color-mix, what you actually want is:

:root {
  --sdColorsRed100: color-mix(in srgb, var(--sdColorsRed200), #fff 10%); 
}

What that means is that when outputReferences is enabled, we would like the color-mix transform to apply after the output references has been put back... which currently happens on format level :\ although we can potentially change that, so let's take a hypothetical scenario, where we don't resolve references to begin with:

Once we hit the color modifier transform, we have:

{
  "colors": {
    "red": {
      "100": {
        "value": "{colors.red.200}",
        "type": "color",
        "$extensions": {
          "studio.tokens": {
            "modify": {
              "type": "lighten",
              "value": "0.1",
              "space": "hsl"
            }
          }
        }
      }
    }
  }
}

What if, the color modifier transform ignores the fact that the value contains references, and runs in it regardless, then we get color-mix(in hsl, {colors.red.200}, #fff 10%). Then finally in the CSS format, we ensure that any references {} get converted to CSS custom properties so we get color-mix(in hsl, var(--colorsRed200), #fff 10%).

So this requires a change to outputReferences where we don't resolve references whatsoever, but it also requires that transforms have the ability to transform values with references in them, again this is also useful for calc() situation with stacking math expressions through reference chains.

This is quite a bit of thinking out loud and throwing examples and maybe exploding this issue a bit as a result, but I think it's really important that we tackle this from all the angles:

  • stacking transitive transforms (resolved references)
  • stacking transitive transforms (not resolving references / outputReferences true)
  • non-stacking transitive transforms (resolved references)
  • non-stacking transitive transforms (not resolving references / outputReferences true)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants