Skip to content

feat(design-tokens): Add a unit on a token value on demand #588

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

Closed

Conversation

fredboyle
Copy link

  • Add the "as" keyword for adding a unit to unit-less token

Example:

JSON

{
    "typography": {
        "size": {
            "small": { "value": 0.8 }
        }
    }
}

CSS

.scope-headings-small {
    font-size: design-token('typography.size.small' as rem);
}

Ouput

.scope-headings-small {
    font-size: 0.8rem;
}

Signed-off-by: Fred Boyle <fred.boyle@pantheon.io>
@romainmenke
Copy link
Member

romainmenke commented Aug 25, 2022

Hi @fredboyle,

Thank you for contributing 🎉


A couple of questions first :

1 why is the unit missing in the tokens file?

If rem is the intended unit for these tokens it should also have rem in the tokens file.
Are they missing for a specific reason? Or is there a tool or program that omits these?

2 is the unit always missing in the tokens file?

Is this consistent?
If they are always missing it will be annoying to always have to type as rem.

3 is this a value or a multiplier?

If they are a value I would expect the tokens to include rem.
If they are a multiplier I can understand why these are missing.

A multiplier assumes a calc expression :

{
  "font-size": 1.25
}
.foo {
  font-size: design-token('font-size' foo rem); /* foo as a placeholder */

  /* resolves to this : */
  font-size: calc(1rem * 1.25);

  /* equivalent to this : */
  font-size: 1.25rem;
}

Understanding this fully will allow us to pick the right API for this.

4 can you use design-token('a.token.path')rem;?

Just adding rem after design-token() works today and doesn't require changes to the plugin.

Can this work for your case?

@fredboyle
Copy link
Author

See responses inline below.

Hi @fredboyle,

Thank you for contributing 🎉

A couple of questions first :

1 why is the unit missing in the tokens file?

If rem is the intended unit for these tokens it should also have rem in the tokens file. Are they missing for a specific reason? Or is there a tool or program that omits these?

Design tokens should be unit-less to be true design tokens usable across multiple platforms. rem is specific to the web context and does not apply to other platforms.

2 is the unit always missing in the tokens file?

Is this consistent? If they are always missing it will be annoying to always have to type as rem.

Our design tokens are cross-platform and as such have no unit unless it is universal. Each platform using the design tokens can decide if a unit is needed and which unit to use.

3 is this a value or a multiplier?

If they are a value I would expect the tokens to include rem. If they are a multiplier I can understand why these are missing.

A multiplier assumes a calc expression :

{
  "font-size": 1.25
}
.foo {
  font-size: design-token('font-size' foo rem); /* foo as a placeholder */

  /* resolves to this : */
  font-size: calc(1rem * 1.25);

  /* equivalent to this : */
  font-size: 1.25rem;
}

Understanding this fully will allow us to pick the right API for this.

Most of our values are multipliers to maintain relationships with each other and scale as needed universally.

4 can you use design-token('a.token.path')rem;?

Just adding rem after design-token() works today and doesn't require changes to the plugin.

Can this work for your case?

Duh! I've been using other technologies too much and such a simple solution went overlooked by me. :)

With this last option being functional already then this pull-request is redundant and not needed. Hopefully my other comments help with an understand of our use of design tokens though.

@fredboyle fredboyle closed this Aug 25, 2022
@fredboyle
Copy link
Author

@romainmenke One small catch-22 I just thought of to the simple solution is formatters such as Prettier like to add spaces between function parentheses and the following content. Not ideal so the as could still be useful in such common scenarios without requiring the old /* prettier-ignore */ line everywhere.

@romainmenke
Copy link
Member

@fredboyle I agree.

plugins/postcss-design-tokens/src/data-formats/style-dictionary/v3/value.ts:71
Currently the tokens are required to have a unit for the transform with to to work.
Can we tweak that to allow assigning units to unit-less values?

.unitless {
	padding-bottom: design-token('space.unitless' to rem);
	padding-bottom: design-token('space.unitless' to px);
}

Then we do not need the new API with as px | as rem.

@fredboyle
Copy link
Author

@romainmenke That would work indeed but should accept any unit. We ourselves also use em and occasionally %. Others in the future may also wish to use viewport based units such as vh or vw and beyond.

@romainmenke
Copy link
Member

True.

Out of curiosity, how do you handle these cases when using design tokens with the generated CSS?

As far as I know these would all become CSS variables without units right?

:root {
  --typography-size-small: 0.8;
}

How do you assign a unit to them in those cases?

@fredboyle
Copy link
Author

Style Dictionary generated CSS custom properties are unit-less at this time for us. We have not yet implemented a transform to add the unit automatically.

So at this time if we use a CSS custom property version of a design token in our CSS we simply use the calc(var(--typography-size-small) * 1rem) trick to give it a unit.

@romainmenke
Copy link
Member

@fredboyle We have just released v1.2.0 with support for this feature :

https://github.com/csstools/postcss-plugins/blob/main/plugins/postcss-design-tokens/CHANGELOG.md#120-september-7-2022

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

Successfully merging this pull request may close these issues.

2 participants