design-tokens / community-group

This is the official DTCG repository for the design tokens specification.
https://tr.designtokens.org
Other
1.56k stars 63 forks source link

Contextual token values #204

Open ilikescience opened 1 year ago

ilikescience commented 1 year ago

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):

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

[comment deleted]

c1rrus commented 1 year ago

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 commented 1 year ago

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.