Skip to content

Commit

Permalink
Clarify usage recommendations, improve examples
Browse files Browse the repository at this point in the history
  • Loading branch information
drwpow committed Jan 14, 2025
1 parent 113aa83 commit 299d636
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 59 deletions.
99 changes: 45 additions & 54 deletions technical-reports/format/aliases.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Aliases / references
# Aliases (References)

Instead of having explicit values, tokens can reference the value of another token. To put it another way, a token can be an alias for another token. This spec considers the terms "alias" and "reference" to be synonyms and uses them interchangeably.

Expand All @@ -7,11 +7,11 @@ Aliases are useful for:
- Expressing design choices
- Eliminating repetition of values in token files (<abbr title="Don’t Repeat Yourself">DRY</abbr>ing up the code)

At any part of the schema, you may refer to another part of the schema with a reference. This follows the usage of `$ref` from the [JSON Schema 2020-12 specification](https://json-schema.org/draft/2020-12/json-schema-core).
At any part of the schema, you MAY refer to another part of the schema with an object that has a `$ref` key and a valid [JSON pointer string](https://datatracker.ietf.org/doc/html/rfc6901). This syntax is borrowed from [JSON Schema (2020-12)](https://json-schema.org/draft/2020-12/json-schema-core#name-schema-references).

### Referencing tokens
### Referencing Tokens

You may reference values in the same file by starting with the fragment character (`#`) followed by the token path, all separated by forward slashes:
You MAY reference values in the same file by starting with the fragment character (`#`) followed by the token path, separated by forward slashes:

<aside class="example">

Expand All @@ -29,34 +29,11 @@ You may reference values in the same file by starting with the fragment characte
}
```

Would resolve to:

```json
{
"color": {
"blue": {
"4": { "$value": "#218bff", "$type": "color" }
},
"brand": {
"$description": "Brand color",
"$value": "#218bff",
"$type": "color"
}
}
}
```
`color.brand` aliases `color.blue.4`, and SHOULD always share its value (even at runtime).

</aside>

In other words, `$ref` will act as if it’s importing the object it’s pointing to, with any sibling values being kept.

Tooling MUST allow `$ref` to have sibling values that act as overrides. In case of a conflict, tooling MUST keep the sibling values to `$ref` (in other words, `$ref` is resolved first, then any sibling keys are applied).

<p class="ednote" title="JSON Schema 2020-12">
JSON Schema 2020-12 was chosen over 2019-09 because it allows sibling overrides alongside `$ref`.
</p>

### Referencing non-tokens
### Aliasing Non-tokens

It’s not just tokens that may be referenced; any part of the document may be referenced. For example, groups:

Expand All @@ -76,34 +53,17 @@ It’s not just tokens that may be referenced; any part of the document may be r
}
```

Would resolve to:

```json
{
"color": {
"gray": {
"1": { "$value": "#101010", "$type": "color" },
"2": { "$value": "#202020", "$type": "color" },
"3": { "$value": "#404040", "$type": "color" },
"4": { "$value": "#808080", "$type": "color" }
},
"grey": {
"1": { "$value": "#101010", "$type": "color" },
"2": { "$value": "#202020", "$type": "color" },
"3": { "$value": "#404040", "$type": "color" },
"4": { "$value": "#808080", "$type": "color" }
}
}
}
```
In this example, `color.grey.1` would be an alias for `color.gray.1`, `color.grey.2` would alias `color.gray.2`, etc.

</aside>

Any group or property (`$type`, `$value`, `$description`, `$extension`, etc.) may all be referenced, so long as the final resolved value results in a valid schema.

### Remote files
### Aliasing Tokens in Other Files

Aliasing tokens from other files is possible by specifing a URL, either relative (`./relative/path.json`) or absolute (`https://example.com/api/v1/tokens.json`).

Referencing remote files may be done by using a valid URL for `$ref`. This may be a relative URL or an absolute URL. To optionally reference a sub-schema, use the fragment character `#` at the end of the URL, and [complete the reference as you would normally](#referencing-tokens).
To only use part of a JSON structure, you MAY use the fragment character (`#`) after the URL, followed by [the token path](#referencing-tokens).

<aside class="example">

Expand All @@ -123,12 +83,43 @@ Referencing remote files may be done by using a valid URL for `$ref`. This may b
```

</aside>

If there is no `#` character, the entire file will be loaded. So this means files MAY contain partial or incomplete schemas. The same rules apply—it MUST resolve to a valid, complete schema in the end.

## Additional info
## Additional Info

When a tool needs the actual value of a token it MUST resolve all aliases and references, i.e. lookup the token being referenced and fetch its value.

Tooling MUST allow `$ref` to have sibling values that act as overrides. In case of a conflict, tooling MUST keep the sibling values to `$ref`, i.e. `$ref` is resolved first, then any sibling keys are applied.

<p class="ednote" title="JSON Schema 2020-12">
JSON Schema 2020-12 was chosen over 2019-09 because it allows sibling overrides alongside `$ref`.
</p>

Tools SHOULD preserve all references, and only resolve them whenever the actual value needs to be retrieved.

<aside class="example">

For example, if a token named `color.text.primary` was an alias of `color.palette.black`, the following CSS SHOULD be generated:

##### ✅ Recommended

When a tool needs the actual value of a token it MUST resolve all aliases and references - i.e. lookup the token being referenced and fetch its value.
```css
:root {
--color-palette-black: #000000;
--color-text-primary: var(--color-palette-black);
}
```

Tools SHOULD preserve references and therefore only resolve them whenever the actual value needs to be retrieved. For instance, in a [=design tool=], changes to the value of a token being referenced by aliases SHOULD be reflected wherever those aliases are being used.
##### ❌ Not Recommended

```css
:root {
--color-palette-black: #000000;
--color-text-primary: #000000;
}
```

</aside>

Aliases MAY reference other aliases. In this case, tools MUST follow each reference until they find a token with an explicit value. Circular references are not allowed. If a design token file contains circular references, then the value of all tokens in that chain is unknown and an appropriate error or warning message SHOULD be displayed to the user.
29 changes: 24 additions & 5 deletions technical-reports/format/terminology.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,33 @@ Groups are arbitrary and tools SHOULD NOT use them to infer the type or purpose

A design token's value can be a reference to another token. The same value can have multiple names or _aliases_.

The following Sass example illustrates this concept:
The following CSS example illustrates this concept:

```scss
$color-palette-black: #000000;
$color-text-primary: $color-palette-black;
```css
:root {
--color-palette-black: #000000;
--color-text-primary: var(--color-palette-black);
}
```

The value of `--color-text-primary` is `#000000`, because `--color-text-primary` _references `--color-palette-black`_. We can also say `--color-text-primary` is an _alias_ for `--color-palette-black.`

In JSON notation, we define an alias the same way as [JSON Schema references](https://json-schema.org/draft/2020-12/json-schema-core#name-schema-references):

```json
{
"color": {
"palette": {
"black": { "$value": "#000000", "$type": "color" }
},
"text": {
"primary": { "$ref": "#/color/palette/black" }
}
}
}
```

The value of `$color-text-primary` is `#000000`, because `$color-text-primary` _references `$color-palette-black`_. We can also say `$color-text-primary` is an _alias_ for `$color-palette-black.`
To learn more about syntax and uses, see [the definition on Aliases](#aliases-references).

## Composite (Design) Token

Expand Down

0 comments on commit 299d636

Please sign in to comment.