Re: [community-group] Object vs Array (#55)

Not sure if this or https://github.com/design-tokens/community-group/issues/72 is better place for this as this tackles both issues. Inspired by some of @c1rrus suggestions and `tokens` prop I made this few simple rules. Benefit would be that there would be just one reserved word for token name ("tokens"). Both object and arrays would be supported, and I see no need for exceptions and special cases.

There is just few things to think about `token`, `tokens group`, and `tokens` key.

## Token
Can contain:
  - Either just value.
  - Either token properties like value, type, description, name, anything. In this case `value` is mandatory.

May not contain:
  - `tokens` prop. This would actually make it a tokens group and all the props would be group props. Even `value` would be just another group prop.

## Tokens group
Must contain:
  - `tokens` prop.

Can contain:
  - none or any number of other group properties like type, description, name, anything... Even `value` would be just another group prop.

`filename.tokens` or `filename.tokens.json` is a tokens group just as any other group containing `tokens`.

## Tokens prop
Can contain:
  - Individual tokens
  - Token groups

It can be both object or array format.

## Summary
- root level of json is a tokens group.
- If some value has a `tokens` prop, it makes it a tokens group.
- If some value doesn't have tokens, it makes it an individual token, so it must have value prop. Unless it is a simple key/value pair where value is value.

That is all :)

## Examples

- token with just a value:
`"primaryColor": "#00ff00"`

- token with properties, where value is mandatory:
```json
"primaryColor": {
    "value": "#00ff00",
    "type": "color",
    "description": "use this color everywhere",
    "name": "Main Color",
    "anything": "You can use any key names and any number of properties, except `tokens` if you want this to be an individual token, not a group. Only `value` is mandatory for an individual token."
}
```

- root level tokens group. You can't add group properties in root level unless you add `tokens` prop. However this is nice option for micro themes.
```json
{
    "primaryColor": "#ff00ff",
    "secondaryColor": "#0000cc",
    "complexToken": {
        "value": "#ff0000",
        "type": "color",
        "description": "description"
    }
}
```

- root level tokens group as array.
```json
[ "#000000", "#ffffff", "#cccccc", "#ccff33"]
```

- adding `tokens` prop makes a tokens group, not an individual token, and all the props will be group props. Even value will be just a non mandatory prop on a group, not the token value.
```json
"color": {
    "value": "Not really a token value, since this is a tokens group.",
    "type": "color",
    "description": "these are our colors",
    "name": "Color Pallete",
    "tokens": {
        "primary": "#00ff00",
        "secondary": "another individual token or tokens group here",
        "value": "value does not mean anything here also since this is also a token group",
        "complexToken": {
            "value": "#ff0000",
            "type": "color",
            "description": "description"
        }
    }
}
```

### Complex example including arrays and how it could translate to css variables

mybrand.tokens
```json
{
    "type": "color",
    "description": "tokens group description",
    "value": "just another prop on the tokens group",
    "tokens": {
        "color": {
            "type": "color",
            "tokens": {
                "primary": {
                    "description": "primary colors and variations",
                    "tokens": {
                        "light": "#000000",
                        "dark": "#ffffff"
                    }
                },
                "secondary": "#00ff00",
                "terciary": {
                    "name": "accent",
                    "value": "#cc55ff"
                }
            }
        },
        "spacing": {
            "horizontalWithObjects": { "s": "2px", "m": "4px", "l": "8px" },
            "verticalWithArrays": [ "2px", "4px", "8px" ],
            "universalWithArraysAndExtraProps": {
                "description": "description",
                "moreProps": "more props",
                "tokens": [
                    { "name": "s", "value": "2px" },
                    { "name": "m", "value": "4px" },
                    { "name": "l", "value": "8px" }
                ]
            }
        },
        "deplyNestedForNoGoodReason": {
            "description": "This group has tokens",
            "tokens": {
                "description": "Instead of actuall tokens just a another tokens group is nested here. Not much sense to design your tokens like this, but things will not break.",
                "type": "dimension",
                "tokens": {
                    "description": "this group will finally have real tokens",
                    "tokens": {
                        "t1": 1,
                        "t2": 2
                    }
                }
            }
        },
        "crazyNames": {
            "description": "Tokens can use any name except `tokens`, including value, type or description",
            "tokens": {
                "type": 1,
                "value": 2,
                "description": 3
            }
        }
    }
}
```
Compiled to CSS

```css
.some-css-selector {
    --color-primary-light: "#000000";
    --color-primary-dark: "#ffffff";
    --color-secondary: "#00ff00";

    --color-terciary: "#cc55ff";
    /* or maybe use name
    --color-accent: "#000000";
    */

    --spacing-horizontalWithObjects-s: "2px";
    --spacing-horizontalWithObjects-m: "4px";
    --spacing-horizontalWithObjects-l: "8px";

    --spacing-verticalWithArrays-0: "2px";
    --spacing-verticalWithArrays-1: "4px";
    --spacing-verticalWithArrays-2: "8px";

    --spacing-universalWithArraysAndExtraProps-0: "2px";
    --spacing-universalWithArraysAndExtraProps-1: "4px";
    --spacing-universalWithArraysAndExtraProps-2: "8px";
    /* or maybe take name
    --spacing-universalWithArraysAndExtraProps-s: "2px";
    --spacing-universalWithArraysAndExtraProps-m: "4px";
    --spacing-universalWithArraysAndExtraProps-l: "8px";
    */

    --deplyNestedForNoGoodReason-t1: 1;
    --deplyNestedForNoGoodReason-t2: 2;

    --crazyNames-type: 1;
    --crazyNames-value: 2;
    --crazyNames-description: 3;
}
```


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


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

Received on Thursday, 23 September 2021 15:01:29 UTC