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

Contextual token values #204

Open
ilikescience opened this issue Jan 21, 2023 · 5 comments
Open

Contextual token values #204

ilikescience opened this issue Jan 21, 2023 · 5 comments

Comments

@ilikescience
Copy link

ilikescience commented Jan 21, 2023

Note
This is meant to be a catchall issue for a number of separate conversations around contextual values. See #188, #169, #135, and #2 for previous conversations

Reading back through issues, it seems like we should make three interlinked decisions soon:

  1. Should the spec support contextual token values? (aka theming, fluid values, conditional values)
    a. If so, what contexts should be supported?
    b. And what should the context be?

My current thinking:

Should the spec support contextual values?

Yes. Changing a design based on context is a major use case for tokens, so it would be good to include it in the spec.

If so, what contexts should be supported?

ONLY those that are independent of platforms. For example (not exhaustive):

  • ✅ Platform-independent :
    • Viewport width
    • Accessibility preferences (high contrast, reduced motion)
    • Color theme
  • ❌ Platform-dependent:
    • version or environment (ie CSS @supports or iOS version)
    • unique units like CSS's lvh, dvb

And what should the syntax be?

@romainmenke 's initial proposal is a good place to start, though I'd recommend calling them "contextual" values instead of "conditional" values.

{
  "backgroundColor": {
    "$type": "color",
    "$value": "cyan",
    "$contextualValues": [
      {
        "$context": "width",
        "$condition": ">500px",
        "$value": "purple"
      },
      {
        "$context": "colorScheme",
        "$condition": "dark",
        "$value": "yellow"
      }
    ]
  }
}

Though an argument could be made for grouping token mappings under contexts like so:

{
  "backgroundColor": {
    "$type": "color",
    "default": {
      "$value": "cyan"
    },
    "context": {
      "wide": {
        "$value": "purple"
      },
      "dark": {
        "$value": "yellow"
      }
    }
  },
  "$contexts": {
    "width": [
      {
        "$condition": ">500px",
        "$contextualValues": {
          "backgroundColor-default": "{backgroundColor-context-wide}"
        }
      }
    ],
    "colorScheme": [
      {
        "$condition": "dark",
        "contextualValues": {
          "backgroundColor-default": "{backgroundColor-context-dark}"
        }
      }
    ]
  }
}

I'm using aliases in the second example to demonstrate how contexts could be additive to grouping.


Overall, I think that we can define a set of contexts that are supported by all target platforms, then define a specification for how the syntax in the token file should be interpreted in each language.

@romainmenke
Copy link
Contributor

I don't think there is much value at this time in supporting platform specific contexts and that it will be problematic to implement in design tools.

There is just no way design tools can provide meaningful and useful UI for all the platform specific contexts of all the possible platforms.

Keeping the scope small is key here, I think.

@ilikescience
Copy link
Author

I don't think there is much value at this time in supporting platform specific contexts and that it will be problematic to implement in design tools.

Agreed!

@kevinmpowell
Copy link
Contributor

kevinmpowell commented Jan 23, 2023

[comment deleted]

@c1rrus
Copy link
Member

c1rrus commented Feb 9, 2023

I agree it would be great to have a mechanism in the format for this kind of thing, but I wonder whether the spec needs to pre-define contexts at all.

What if we let people provide any number of alternative values for a given token, each with a user-defined identifier. For example:

{
  "mighty-morphing-token": {
    "$type": "dimension",
    "$value": "16px",
    "$altValues": {
      "high-info-density": "12px",
      "low-info-density": "20px",
      "random-thing": "17px"
    }
  }
}

From a tooling perspective, the only requirement would be to let the user to provide one (or more?) of their chosen keys and then resolve token values to the corresponding $altValue if it exists. Where non exists, $value is used as a fallback.

So the above token's value would be 16px by default, but if the user has asked the tool to prefer "low-info-density" values, ot would resolve to 20px instead.

Example 1: Translation tool

A translation tool like Style Dictionary could let the user pass in desired alt value keys via a command-line option or config file.

Let's imagine we have such a tool, usage could look something like this:

$ dtcg2css input.tokens.json > output.css

Might use default values and produce something like:

:root {
  --mighty-morphing-token: 16px;
}

But running it like this:

$ dtcg2css --alt-value=random-thing input.tokens.json > output-random.css

...would produce:

:root {
  --mighty-morphing-token: 17px;
}

Example 2: UI design tool

A design tool like Figma might present a list of all alt value keys in a .tokens file to the user and let them pick which one(s) to apply.

Wherever they've used those tokens in their designs, the design would update to show the currently applied settings.

I'm imagining the experience to be similar to how you can switch "token sets" on and off in the Tokens Studio Figma plug-in.

@romainmenke
Copy link
Contributor

romainmenke commented Feb 9, 2023

I agree it would be great to have a mechanism in the format for this kind of thing, but I wonder whether the spec needs to pre-define contexts at all.

What if we let people provide any number of alternative values for a given token, each with a user-defined identifier. For example:

I fear this would not be useful.
I also don't see how it is different from regular groups.

Because this is all user defined we can not add any logic for it in translation tools.
It would be extra complexity without any extra features.


What I want to provide as a translation tool implementer is a way to generate this :

body {
  color: yellow;
}

@media (prefers-color-scheme: dark) {
  body {
    color: cyan;
  }
}

I want to be able to generate this from only this information in the CSS :

body {
  color: token('my-color');
}

This is a different feature than a toggle to load different values for theming purposes.
You can easily generate multiple themes by running whatever build process multiple times with different input.

But dynamic values for different viewport sizes, accessibility settings, ... must be in the same output.


For theming we provide a specific API that allows users to write CSS once : https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-design-tokens#is

Users just import different tokens files and declare the set of conditions that must be true for the tokens to be actually used.

They then toggle these conditions in their build process, making it easy to write CSS once and extrapolate to multiple themes.

This entire feature just uses multiple token files, so it doesn't have to be part of the specification.

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

No branches or pull requests

4 participants