Re: [community-group] Native modes and theming support (#210)

Thanks for sharing this thorough proposal @jjcm, and thanks everyone else for all the insightful comments here!

Overall, I really like this proposal. I think it would provide the format with an elegant mechanism for providing alternate token values for any number of use-cases. As Jake pointed out in the previous comment, this could have applications way beyond light and dark color schemes.

Of course, since the modes are author-defined (i.e. there wouldn't be a pre-defined set of permitted mode names in the spec), tools can't automatically infer any semantics from the mode names or apply specialised functionality based on the selected mode.

If I understood correctly, I think this is essentially the issue @romainmenke raisedin his comments. For example, a translation tool could not "know“ that a particular mode is represents the colors that should be used when the user has set their OS to dark mode and therefore could not automatically output an appropriate `@media` query in CSS.

However, I think the `$modes` proposal nonetheless enables a lot of use-cases that are so far impossible to represent using the current DTCG format draft. I'd therefore be in favour of adding it to the spec.

I do think some of the finer details need ironing out first though...

### Does `$value` really need to be optional?

The OP proposal relaxes the requirement for every token to have a `$value` since could instead just have `$modes`. While this certainly could be done, I wonder whether it might keep things a bit more consistent and simple if we keep `$value` being mandatory.

The way I see it, every DTCG file has an implied "default" mode, which is what you get if you didn't use `$modes` at all. So why not lean into that and encourage authors to only use `$modes` for _additional_ modes they might need.

Taking the initial example from the OP, we might decide that "light" is our default and therefore only use `$modes` to create the additional "dark" and "super-dark" modes. The example could then be rewritten as:

```jsonc
{
  "$modes": {
    // no longer specify light
    "dark":       {}, // no fallback
    "super-dark": { "$fallback": "dark" }
  },
  "bg": {
    "$type": "color",
    "brand": {
      "$value": "{colors.blue.300}", // light mode falls back to this
      "$modes": {
        "dark": "{colors.blue.500}" // super-dark mode falls back to this
      }
    }
  },
  "fg": {
    "$type": "color",
    "brand": {
      "$value": "{colors.black}", // use $value rather than $modes.light here
      "$modes": {
        "dark": "{colors.white}",
        "super-dark": "{colors.gray}"
      }
    }
  }
}
```

I think doing it this way and retaining the "every token must have a `$value`" rule is preferable for the following reasons:

* Avoids situations where an author omits `$value` but forgets to specify `$modes` values for every mode. In that case there'd be no `$value` to fall back on, so the token becomes... invalid?
* Could make the learning curve for the format lower since there's less exceptions to learn. I think "every token must have a `$value`" is simpler than "every token must have a `$value`, _unless it has a `$modes` property_". Especially if you consider `$modes` an advanced feature that newcomers might not learn about right away.
* Keeps parser logic a (tiny bit) simpler too for the same reason as above.

I think the only thing we might lose would be the ability to assign a name the default mode. In the above example, users would need to know that "no mode means light mode". However, we could solve that by having a means to provide optional metadata about the default mode. For example, we could have an optional `$defaultMode` property that could be added to the top-level `$modes` declaration like so:

```jsonc
{
  "$modes": {
    "$defaultMode": {
      "$name": "light"
    },
    "dark":       {}, // no fallback
    "super-dark": { "$fallback": "dark" }
  },
 // ...
}
```

#### Could modes have additional metadata?

For example `$description`? I could imagine this might be useful for tools that have the ability to list out all declared modes to the user.

```jsonc
{
  "$modes": {
    "$defaultMode": {
      "$name": "light",
      "$description": "A color scheme to be used when the user has expressed a preference for a light UI"
    },
    "dark": {
      "$description": "A color scheme to be used when the user has expressed a preference for a dark UI"
    },
    "super-dark": {
      "$description": "A even darker version of the dark color scheme which uses pure black backgrounds to preserve energy on devices with OLED displays",
      "$fallback": "dark" 
    }
  },
 // ...
}
```

It's conceivable that future spec iterations might add more properties for other bits of useful metadata for tokens and groups. When doing so, we could also consider whether they might be useful for mode declarations and, if so, permit them to be used here.

#### Should modes have `$extensions`?

Sort of related to the previous point, maybe permitting `$extensions` on mode declarations could be useful too. The use-case would be extensions that relate to a mode itself rather than a token or group.

This kind of thing could perhaps enable tools to add some additional semantics per mode, as @TravisSpomer was [suggesting](https://github.com/design-tokens/community-group/issues/210#issuecomment-1481615300) in response to @romainmenke.

E.g.:

```jsonc
{
  "$modes": {
    "$defaultMode": {
      "$name": "light",
      "$extensions": {
        "org.postcss.design-tokens.media-query": "(prefers-color-scheme: light)" 
      }
    },
    "dark": {
      "$extensions": {
        "org.postcss.design-tokens.media-query": "(prefers-color-scheme: dark)" 
      }
    },
    "super-dark": {
      "$extensions": {
        "org.postcss.design-tokens.media-query": "(prefers-color-scheme: dark) and (prefers-contrast: more)" 
      },
      "$fallback": "dark" 
    }
  },
 // ...
}
```

Obviously, the standard `$extensions` caveat of being prorietary and thus not universally supported by tools applies. But this could still provide an "escape hatch" to enable tool-specific functionality. Also, if particular extensions gain a lot of adoption, it provides us with a cowpath to pave in future spec iterations.

-- 
GitHub Notification of comment by c1rrus
Please view or discuss this issue at https://github.com/design-tokens/community-group/issues/210#issuecomment-1489938093 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Thursday, 30 March 2023 08:54:11 UTC