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

Unable to use multiple transformers with the same token type #1317

Open
equinusocio opened this issue Aug 22, 2024 · 8 comments
Open

Unable to use multiple transformers with the same token type #1317

equinusocio opened this issue Aug 22, 2024 · 8 comments
Labels

Comments

@equinusocio
Copy link

equinusocio commented Aug 22, 2024

The issue

Hello, in our design system we have some tokens that must be converted to px and other to rem. Since both size/pxToRem and size/px, check on the token.type === 'dimension' we can't use the built-in transformers because the output would be all px or all rem. We are forced to create custom transformers only to change the filter function and check on different type. Doing so makes the built-in transformers concept a bit useless.

Possible solution

In our opinion, transformers should have unique filter check to being able to combine them on the same platform. For instance size/pxToRem could match type === 'dimension-px-to-rem' and size/px could match type === 'dimension-px'. This way we can convert some tokens to px, and some to rem

@jorenbroekema
Copy link
Collaborator

Transforms can be chained on the same type, but yes for size/pxToRem and size/px they both expect the input to be unitless, so in that particular case chaining them won't do much since only the first transform will actually take effect.

If you're only interested in changing the filter of a transform for a particular built-in transform, consider trying this:

Example from #1292

const colorHslBuiltin = StyleDictionary.hooks.transforms['color/hsl'];
StyleDictionary.registerTransform({
  ...colorHslBuiltin,
  filter: (token) => token.type === 'colors',
  name: 'colors/hsl', // if you don't override the name it will register on the original name and override the built-in one, which might be nice
});

@equinusocio
Copy link
Author

equinusocio commented Aug 29, 2024

Thank you, my input is unitless, but when the token type is dimension only the latest transform with filter dimension defined in the custom group is used (or replace the previous ones with the same filter)

Giving this custom transform group:

[
  'size/rem',
  'size/px'
]

and the following tokens:

{
  "font": {
    "size-px": {
      "$type": "dimension",
      "100": {
        "$value": 100
      }
    },
    "size-rem": {
      "$type": "dimension",
      "100": {
        "$value": 100
      }
    }    
  }
}

both final tokens are in px because the size/px transform comes after in the custom group.


Is there any possibility of seeing the proposed change and avoiding writing "fake" custom transform to change the filter? Does it make sense to have non-exclusive transforms?

@jorenbroekema
Copy link
Collaborator

So your proposal is to somehow make size/rem and size/px mutually exclusive from being used within the same platform?

The issue is that just because their filter methods overlap, it doesn't mean they can't work in conjunction with one another.
E.g. ['color/rgb', 'color/lab'] (these are hypothetical transforms), you may need to first transform a color from hex to rgb before the color/lab can transform it to oklab, because maybe that transform happens to not support hex as input.
Maybe not the greatest example but "daisy chaining" transforms on the same token type definitely has its use cases

@equinusocio
Copy link
Author

equinusocio commented Aug 29, 2024

In your chain example, you have one token input, converted to RGB, then converted to LAB, a sigle output. Yes, this chain may be useful, but honestly, we find it more common in design systems to have tokens with the same type that need different output. Platforms support many “types”, in our case, the web platform supports line height in px, em, rem, etc… both are “dimension” types with different use cases and one doesn’t exclude the others. In the example above, if we want to convert the same token to multiple units we are forced to create a custom transform.

If there is a way to make chaining and this change work together is even better.
Maybe an extra config to explicitly define transforms to be chained?

@jorenbroekema
Copy link
Collaborator

I think if you want to transform two tokens differently yet they share the same type, you'll have to add some metadata to the token to be able to distinguish between these tokens if the type is the same. I'm not convinced currently about your proposed changes to complicate the transforms API to be able to do this when there's an easier way to do it already

@equinusocio
Copy link
Author

What easier way? Defining custom fake transforms?

@jorenbroekema
Copy link
Collaborator

Yes overriding the built-in transforms either partially or entirely, or creating a custom transform and using that instead. The built-ins aren't meant to be perfect for everyone - custom transforms is already how people get around it, overriding the built-ins is often more convenient but just needs more documentation

@equinusocio
Copy link
Author

ok. It's worth taking into consideration that the software's assumption of only one output for token type may not align conceptually with the diverse needs of different platforms or design systems. For instance, using the type "dimension/rem" could potentially lead to the software enforcing the use of only rem throughout the platform. It's definitely a point worth considering.

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

No branches or pull requests

2 participants