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]: Transform px dimensions to number values #238

Closed
1 task
fwielstra opened this issue Jan 3, 2024 · 4 comments
Closed
1 task

[Feature]: Transform px dimensions to number values #238

fwielstra opened this issue Jan 3, 2024 · 4 comments
Labels
question Question about sd-transforms/style-dictionary

Comments

@fwielstra
Copy link

fwielstra commented Jan 3, 2024

What feature would you like?

At the moment there is the ts/size/px transformation that transforms numeric values to pixel values, e.g. 12 to "12px"; the transformer is found here: https://github.com/tokens-studio/sd-transforms/blob/main/src/transformDimension.ts

I'm looking for the inverse; in our project, from Token Studio we get a JSON containing pixel values, and the target is a React Native project that uses plain numbers for these values.

At the moment we've built some code that transforms it at runtime, but it would be great if this could be done during transformation already.

That is, a transformer that takes this:

{
  "token": {
    "type": "dimension",
    "value": "4px"
  }
}

and transforms it to this

{
  "token": {
    "type": "dimension",
    "value": 4
  }
}

Would you be available to contribute this feature?

  • Yes, I would like to contribute this
@fwielstra fwielstra added the enhancement New feature or request label Jan 3, 2024
@fwielstra
Copy link
Author

fwielstra commented Jan 3, 2024

Upon actually reading the manual, it looks like it should be easy to add a custom transform that does this:

StyleDictionary.registerTransform({
  name: "my/size/px",
  type: "value",
  transitive: true,
  matcher: (token) => {
    return typeof token.value == "string" && token.value.endsWith("px");
  },
  transformer: (token) => {
    return Number(token.value.replace(/\D/g, ""));
  },
});

However, it does not seem like this transformer is called (the matcher or transformer functions are not called); is there an issue in my configuration? Does the mix of registerTransforms and StyleDictionary.registerTransform cause issues? My full transform code is as follows:

#!/usr/bin/env node
import { registerTransforms } from "@tokens-studio/sd-transforms";
import { promises } from "fs";
import StyleDictionary from "style-dictionary";

registerTransforms(StyleDictionary, {
  expand: {
    typography: true,
  },
  "ts/color/modifiers": {
    format: "hex",
  }
});

StyleDictionary.registerTransform({
  name: "my/size/px",
  type: "value",
  transitive: true,
  matcher: (token) => {
    return typeof token.value == "string" && token.value.endsWith("px");
  },
  transformer: (token) => {
    return Number(token.value.replace(/\D/g, ""));
  },
});

async function run() {
  const $themes = JSON.parse(
    await promises.readFile("./src/tokens/$themes.json", "utf-8")
  );
  const configs = $themes
    .filter((theme) => theme.group === "app")
    .map((theme) => {
      // Only use token set if enabled and in the app group
      const source = Object.entries(theme.selectedTokenSets)
        .filter(([, val]) => val !== "disabled" && theme.group === "app")
        .map(([tokenset]) => `./src/tokens/${tokenset}.json`);

      //convert theme name from kebab-case to camelCase for -light and -dark theme names
      const destinationName = theme.name.replace("-l", "L").replace("-d", "D");

      return {
        source: source,
        name: "test",
        platforms: {
          "react-native": {
            transformGroup: "tokens-studio",
            files: [
              {
                destination: `./src/transformed-tokens/${destinationName}.json`,
                format: "json/nested",
              },
            ],
          },
        },
      };
    });

  configs.forEach((cfg) => {
    const sd = StyleDictionary.extend(cfg);
    sd.cleanAllPlatforms();
    sd.buildAllPlatforms();
  });
}

run();

@jorenbroekema
Copy link
Member

jorenbroekema commented Jan 3, 2024

Hi, yes indeed you can do it with a custom transform.
The issue in your code is that you're registering the transform, but it's not used in the tokens-studio transformGroup.

Refer to this section in the README on how to create a custom transform group that combines your custom transform with the ones from this package: https://github.com/tokens-studio/sd-transforms?tab=readme-ov-file#custom-transform-group

Coincidentally the example in the readme filters out the ts/size/px transform, which I think makes sense for your use case as well, no point in letting that transform do work that your transform will be undoing ;)

Let me know if you manage to get it working!

Edit: I'm curious, as someone that doesn't know much about React Native, do you consider this its own platform, separate from "web" or "flutter" or "ios" or "android"? Perhaps it makes sense for us to add it here: #134 , if so, I'd love to get some context on what kind of transformations you think makes sense for React Native, so that eventually we can make this as simple as registerTransforms(StyleDictionary, { platform: 'react-native' });

@jorenbroekema jorenbroekema added question Question about sd-transforms/style-dictionary and removed enhancement New feature or request labels Jan 3, 2024
@fwielstra
Copy link
Author

Goedemorgen @jorenbroekema, thanks for the reply!

Your suggestion worked! I can now apply a few custom transforms; there were a few other transformations that I've applied (string to number and the like) that I did in code after transformation before, thanks for the help!

As for your other question, yes, I would consider react-native to be its own platform; it's very close to CSS in terms of semantics, key names and the like, but it uses JSON.

In our particular use case, we have a set of tokens that follow a Material Design structure; with minimal transformations, we can convert the tokens to a JSON that matches the structure of the theme type of the component library we use, react-native-paper, the theme type is declared here.

I can post more context if you'd like, once I've cleaned up our transformed-json-to-MD3Theme code now that the transformation does more work?

@jorenbroekema
Copy link
Member

jorenbroekema commented Jan 11, 2024

Yeah would be nice :)

Does react-native support the same shorthands for typography, border and shadow?

For example:

{
  "font": "300 italic 20px/1.5 'Arial Narrow', Arial, sans-serif",
  "box-shadow": "5px 3px 6px 2px #000000",
  "border": "5px dashed rgba(0, 0, 0, 1)"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Question about sd-transforms/style-dictionary
Projects
None yet
Development

No branches or pull requests

2 participants