Re: [community-group] How to do tokens that share a name with a group (#97)

@TravisSpomer In light of the recent comments on the reserved words issue (#61), I wonder if combination of the prefix idea there and what you've suggested could work:

Let's imagine for a moment we use a special prefix like `$` or `_` for all properties in our spec that have a special meaning (value, type, description, etc.) across both groups and tokens. Then we could have a "special" property on groups, for example `$default`, that can be used when you want a token in that group which shares the same name in some contexts (e.g. when being exported as code).

So, it could look like this (if we assume `_` as our universal reserved word prefix):

```jsonc
{
  "color": {
    "accent": {
      "_default": {
        "_type": "color",
        "_value": "#dd0000"
      },
      "light": {
        "_type": "color",
        "_value": "#ff2222"
      },
      "dark": {
        "_type": "color",
        "_value": "#aa0000"
      }
    }
  }
}
```

I've been thinking lately about the tree data model that our token files describe (similar to how HTML files define a DOM) and, in the context of this issue, was wondering if that default color token is logically a child of the accent group or a child of the color group. Personally, I'm leaning towards the latter. In this example it makes more sense to me to think of all 3 are accent colors, as opposed to 1 arbitrary color + 2 accent colors. It's just so happens that one of those accent colors doesn't need a further suffix appended to its name when exported as code.

I therefore like this kind of approach, where that default token is still something _within_ the group. The hybrid approaches lift it up a level in the hierarchy and that doesn't feel right to me.

If we did something like `_default`, I think it could referenced as `{color.accent._default}`, but perhaps as a convenient shorthand you'd also be allowed to do `{color.accent}`. The rule that parsers could follow could be that a reference pointing to a group would resolve to the `_default` token in that group if it exists or be invalid otherwise.

But, I am intrigued by @TravisSpomer's desire to be able reference groups some day. I think there is a way that could co-exist with the `_default` referencing shorthand I've just proposed. My reading of his example is that `button.text` is actually a _group_ referencing another group as a shortcut to create a batch of alias tokens.

So, rather than make the value of `button.text` be something that looks like a token (since it has a `value` property), why not do this:

```jsonc
{
  "neutralcontrol": {
    "foreground": {
      "_type": "color",
      "rest": { "_value": "{...}" },
      "hover": { "_value": "{...}" },
      "pressed": { "_value": "{...}" },
      "disabled": { "_value": "{...}" }
    },
    "background": {
      "_type": "color",
      "rest": { "_value": "{...}" },
      "hover": { "_value": "{...}" },
      "pressed": { "_value": "{...}" },
      "disabled": { "_value": "{...}" }
    }
  },
  "button":
  {
    "text": {
      // The value is no longer an object with a token property and therefore
      // not a token. So, when a "bare" reference like this is encountered parsers
      // are required to interpret it as a *group* reference.
      "color": "{neutralcontrol.foreground}" 
    },
    "base": {
      "color": "{neutralcontrol.background}"
    }
  }
}
```

Even if `{neutralcontrol.foreground}` contained a `_default` token, parsers would know not treat the _group_ reference as a shortcut to that default token. Instead, you'd get `button.text.color._default` being an alias token for `neutralcontrol.foreground._default`.

That could actually be quite nice if you'd prefer to use `_default` instead of `rest` in your naming:


```jsonc
{
  "neutralcontrol": {
    "foreground": {
      "_type": "color",
      "_default": { "_value": "{...}" },
      "hover": { "_value": "{...}" },
      "pressed": { "_value": "{...}" },
      "disabled": { "_value": "{...}" }
    },
    "background": {
      "_type": "color",
      "_default": { "_value": "{...}" },
      "hover": { "_value": "{...}" },
      "pressed": { "_value": "{...}" },
      "disabled": { "_value": "{...}" }
    }
  },
  "button":
  {
    "text": {
      // The value is no longer an object with a token property and therefore
      // not a token. So, when a "bare" reference like this is encountered parsers
      // are required to interpret it as a *group* reference.
      "color": "{neutralcontrol.foreground}" 
    },
    "base": {
      "color": "{neutralcontrol.background}"
    }
  }
}
```

An export tool outputting SASS might then produce something along the lines of:

```scss
$neutralcontrol-foreground: #... ;
$neutralcontrol-foreground-hover: #...;
$neutralcontrol-foreground-pressed: #...;
// etc...

$button-text-color: $neutralcontrol-foreground;
$button-text-color-hover: $neutralcontrol-foreground-hover;
$button-text-color-pressed: $neutralcontrol-foreground-pressed;
// etc...
```

What do you think?

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


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

Received on Thursday, 13 January 2022 23:28:12 UTC