@adobe/design-data-spec 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/conformance/README.md +19 -0
- package/conformance/invalid/SPEC-001/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-001/fixture.json +6 -0
- package/conformance/invalid/SPEC-002/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-002/token-bad-alias.json +7 -0
- package/conformance/invalid/SPEC-002/token-color.json +7 -0
- package/conformance/invalid/SPEC-003/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-003/token-a.json +7 -0
- package/conformance/invalid/SPEC-003/token-b.json +7 -0
- package/conformance/invalid/SPEC-004/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-004/token-one.json +7 -0
- package/conformance/invalid/SPEC-004/token-two.json +7 -0
- package/conformance/invalid/SPEC-005/dimension.json +6 -0
- package/conformance/invalid/SPEC-005/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-006/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-006/token-high.json +8 -0
- package/conformance/invalid/SPEC-006/token-low.json +8 -0
- package/conformance/valid/baseline-token.json +7 -0
- package/package.json +38 -0
- package/rules/rules.yaml +66 -0
- package/schemas/dimension.schema.json +39 -0
- package/schemas/manifest.schema.json +72 -0
- package/schemas/token.schema.json +153 -0
- package/schemas/value-types/color.schema.json +8 -0
- package/spec/cascade.md +54 -0
- package/spec/dimensions.md +55 -0
- package/spec/index.md +86 -0
- package/spec/manifest.md +54 -0
- package/spec/token-format.md +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# [**@adobe/design-data-spec**](https://github.com/adobe/spectrum-design-data/tree/main/packages/design-data-spec)
|
|
2
|
+
|
|
3
|
+
Normative **Design Data Specification** artifacts for Spectrum: human-readable spec (`spec/`), JSON Schemas (`schemas/`), validation rule catalog (`rules/`), and conformance fixtures (`conformance/`).
|
|
4
|
+
|
|
5
|
+
**Spec version:** `1.0.0-draft` — see [`spec/index.md`](spec/index.md).
|
|
6
|
+
|
|
7
|
+
## Layers
|
|
8
|
+
|
|
9
|
+
1. **JSON Schemas** (Draft 2020-12) — structural (per-file) validation; canonical `$id` under `https://opensource.adobe.com/spectrum-design-data/schemas/v0/`.
|
|
10
|
+
2. **Rule catalog** (`rules/rules.yaml`) — semantic rules (`SPEC-001` … `SPEC-006`).
|
|
11
|
+
3. **Conformance fixtures** — valid/invalid examples and expected diagnostics for implementors.
|
|
12
|
+
|
|
13
|
+
## Package exports
|
|
14
|
+
|
|
15
|
+
`package.json` `exports` expose root schemas, `value-types/color.schema.json`, and `rules/rules.yaml` for tooling.
|
|
16
|
+
|
|
17
|
+
## Tasks
|
|
18
|
+
|
|
19
|
+
- `moon run designDataSpec:check` — verify required paths exist (layout guard).
|
|
20
|
+
|
|
21
|
+
## References
|
|
22
|
+
|
|
23
|
+
- [Design Data Specification project](https://github.com/orgs/adobe/projects/89)
|
|
24
|
+
- Discussion [#714](https://github.com/adobe/spectrum-design-data/discussions/714) — umbrella spec
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Conformance fixtures (Layer 3)
|
|
2
|
+
|
|
3
|
+
Each **invalid** case lives under `invalid/<RULE_ID>/` with:
|
|
4
|
+
|
|
5
|
+
- One or more JSON **fixture** files (structurally valid for Layer 1 when targeting Layer 2 rules).
|
|
6
|
+
- **`expected-errors.json`** — expected diagnostics after Layer 2 validation (see `errors[].rule_id`, `severity`, optional `message_pattern`).
|
|
7
|
+
|
|
8
|
+
**Valid** baselines live under `valid/`.
|
|
9
|
+
|
|
10
|
+
| Folder | Rule | Intent |
|
|
11
|
+
| ------------------ | -------- | ------------------------------------------------- |
|
|
12
|
+
| `invalid/SPEC-001` | SPEC-001 | Alias target does not exist. |
|
|
13
|
+
| `invalid/SPEC-002` | SPEC-002 | Alias resolves to incompatible type (semantic). |
|
|
14
|
+
| `invalid/SPEC-003` | SPEC-003 | Circular alias chain. |
|
|
15
|
+
| `invalid/SPEC-004` | SPEC-004 | Duplicate `uuid` across tokens. |
|
|
16
|
+
| `invalid/SPEC-005` | SPEC-005 | Dimension `default` not in `modes`. |
|
|
17
|
+
| `invalid/SPEC-006` | SPEC-006 | Ambiguous resolution / specificity tie (warning). |
|
|
18
|
+
|
|
19
|
+
Implementors SHOULD run these fixtures once the Rust validator exposes rule IDs ([#724](https://github.com/adobe/spectrum-design-data/issues/724), [#725](https://github.com/adobe/spectrum-design-data/issues/725)).
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adobe/design-data-spec",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Design Data Specification — prose, JSON Schemas, rule catalog, and conformance fixtures for Spectrum design data",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/adobe/spectrum-design-data.git",
|
|
9
|
+
"directory": "packages/design-data-spec"
|
|
10
|
+
},
|
|
11
|
+
"author": "Garth Braithwaite <garthdb@gmail.com> (https://garthdb.com/)",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/adobe/spectrum-design-data/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/adobe/spectrum-design-data/tree/main/packages/design-data-spec#readme",
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20.12.0",
|
|
19
|
+
"pnpm": ">=10.17.1"
|
|
20
|
+
},
|
|
21
|
+
"packageManager": "pnpm@10.17.1",
|
|
22
|
+
"exports": {
|
|
23
|
+
"./package.json": "./package.json",
|
|
24
|
+
"./schemas/token.schema.json": "./schemas/token.schema.json",
|
|
25
|
+
"./schemas/dimension.schema.json": "./schemas/dimension.schema.json",
|
|
26
|
+
"./schemas/manifest.schema.json": "./schemas/manifest.schema.json",
|
|
27
|
+
"./schemas/value-types/color.schema.json": "./schemas/value-types/color.schema.json",
|
|
28
|
+
"./rules/rules.yaml": "./rules/rules.yaml"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"spec",
|
|
32
|
+
"schemas",
|
|
33
|
+
"rules",
|
|
34
|
+
"conformance",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {}
|
|
38
|
+
}
|
package/rules/rules.yaml
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Validation rule catalog (Layer 2) — stable IDs for diagnostics and conformance.
|
|
2
|
+
# spec_version aligns with the human-readable spec (see spec/index.md).
|
|
3
|
+
spec_version: "1.0.0-draft"
|
|
4
|
+
rules:
|
|
5
|
+
- id: SPEC-001
|
|
6
|
+
name: alias-target-exists
|
|
7
|
+
severity: error
|
|
8
|
+
category: reference-integrity
|
|
9
|
+
assert: Every alias $ref MUST resolve to an existing token in the dataset.
|
|
10
|
+
message: "Alias target not found for $ref: {path}"
|
|
11
|
+
spec_ref: spec/token-format.md#alias-ref
|
|
12
|
+
introduced_in: "1.0.0-draft"
|
|
13
|
+
|
|
14
|
+
- id: SPEC-002
|
|
15
|
+
name: alias-type-compatibility
|
|
16
|
+
severity: error
|
|
17
|
+
category: type-safety
|
|
18
|
+
assert: Resolved alias target MUST have a value type compatible with the referencing token’s expected type.
|
|
19
|
+
message: "Alias {path} resolves to incompatible type"
|
|
20
|
+
spec_ref: spec/token-format.md#literal-value
|
|
21
|
+
introduced_in: "1.0.0-draft"
|
|
22
|
+
|
|
23
|
+
- id: SPEC-003
|
|
24
|
+
name: no-circular-aliases
|
|
25
|
+
severity: error
|
|
26
|
+
category: reference-integrity
|
|
27
|
+
assert: Alias chains MUST NOT contain cycles.
|
|
28
|
+
message: "Circular alias chain detected involving {path}"
|
|
29
|
+
spec_ref: spec/token-format.md#alias-ref
|
|
30
|
+
introduced_in: "1.0.0-draft"
|
|
31
|
+
|
|
32
|
+
- id: SPEC-004
|
|
33
|
+
name: uuid-global-uniqueness
|
|
34
|
+
severity: error
|
|
35
|
+
category: completeness
|
|
36
|
+
assert: Token uuid values MUST be unique across all token documents in the dataset.
|
|
37
|
+
message: "Duplicate uuid {uuid}"
|
|
38
|
+
spec_ref: spec/token-format.md#lifecycle-and-metadata
|
|
39
|
+
introduced_in: "1.0.0-draft"
|
|
40
|
+
|
|
41
|
+
- id: SPEC-005
|
|
42
|
+
name: cascade-coverage
|
|
43
|
+
severity: error
|
|
44
|
+
category: completeness
|
|
45
|
+
assert: Dimension declarations MUST satisfy coverage rules (e.g. default ∈ modes; peer mode requirements from coverage metadata).
|
|
46
|
+
message: "Dimension coverage violation for {dimension}"
|
|
47
|
+
spec_ref: spec/dimensions.md#coverage-validation
|
|
48
|
+
introduced_in: "1.0.0-draft"
|
|
49
|
+
|
|
50
|
+
- id: SPEC-006
|
|
51
|
+
name: specificity-correctness
|
|
52
|
+
severity: warning
|
|
53
|
+
category: type-safety
|
|
54
|
+
assert: When two tokens from the same layer match a context, the more specific name object MUST win; ties MUST be reported.
|
|
55
|
+
message: "Ambiguous cascade resolution (specificity tie) for context {context}"
|
|
56
|
+
spec_ref: spec/cascade.md#semantic-specificity
|
|
57
|
+
introduced_in: "1.0.0-draft"
|
|
58
|
+
|
|
59
|
+
- id: SPEC-007
|
|
60
|
+
name: name-roundtrip
|
|
61
|
+
severity: warning
|
|
62
|
+
category: naming-consistency
|
|
63
|
+
assert: Every legacy token name MUST be reproducible from a structured name object via deterministic generation rules, unless listed in naming-exceptions.json.
|
|
64
|
+
message: "Token '{token}' does not roundtrip through name-object generation rules"
|
|
65
|
+
spec_ref: spec/token-format.md#name-object
|
|
66
|
+
introduced_in: "1.0.0-draft"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/dimension.schema.json",
|
|
4
|
+
"title": "Dimension declaration",
|
|
5
|
+
"description": "Layer 1 — declares a dimension name, allowed modes, and default. default ∈ modes is validated in Layer 2 (SPEC-005) where needed.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name", "modes", "default"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"specVersion": {
|
|
10
|
+
"const": "1.0.0-draft"
|
|
11
|
+
},
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"minLength": 1
|
|
15
|
+
},
|
|
16
|
+
"modes": {
|
|
17
|
+
"type": "array",
|
|
18
|
+
"items": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"minLength": 1
|
|
21
|
+
},
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"uniqueItems": true
|
|
24
|
+
},
|
|
25
|
+
"default": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1
|
|
28
|
+
},
|
|
29
|
+
"description": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"coverage": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"description": "Optional machine-readable coverage hints (interpreted by Layer 2).",
|
|
35
|
+
"additionalProperties": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"additionalProperties": false
|
|
39
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/manifest.schema.json",
|
|
4
|
+
"title": "Platform manifest",
|
|
5
|
+
"description": "Layer 1 — platform repo declaration of foundation pin and optional filters/overrides.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["specVersion", "foundationVersion"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"specVersion": {
|
|
10
|
+
"const": "1.0.0-draft"
|
|
11
|
+
},
|
|
12
|
+
"foundationVersion": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"minLength": 1,
|
|
15
|
+
"description": "Pin to a foundation release (semver or tag)."
|
|
16
|
+
},
|
|
17
|
+
"include": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"minLength": 1
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"exclude": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"overrides": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": {
|
|
34
|
+
"oneOf": [
|
|
35
|
+
{
|
|
36
|
+
"type": "object",
|
|
37
|
+
"required": ["target", "value"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"target": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"minLength": 1
|
|
42
|
+
},
|
|
43
|
+
"value": true
|
|
44
|
+
},
|
|
45
|
+
"additionalProperties": false
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"type": "object",
|
|
49
|
+
"required": ["target", "$ref"],
|
|
50
|
+
"properties": {
|
|
51
|
+
"target": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"minLength": 1
|
|
54
|
+
},
|
|
55
|
+
"$ref": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"minLength": 1
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"additionalProperties": false
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"extensions": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"description": "Platform-local tokens or dimensions; structure validated by separate documents.",
|
|
68
|
+
"additionalProperties": true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"additionalProperties": false
|
|
72
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/token.schema.json",
|
|
4
|
+
"title": "Design data token",
|
|
5
|
+
"description": "Layer 1 — structural token shape (name + value or alias). Graph rules are Layer 2.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"oneOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "#/$defs/tokenWithValue"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "#/$defs/tokenWithRef"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"$defs": {
|
|
16
|
+
"nameObject": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"description": "Structured token identity; additional dimension keys MUST be strings.",
|
|
19
|
+
"required": ["property"],
|
|
20
|
+
"properties": {
|
|
21
|
+
"property": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1
|
|
24
|
+
},
|
|
25
|
+
"component": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"variant": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"state": {
|
|
32
|
+
"type": "string"
|
|
33
|
+
},
|
|
34
|
+
"colorScheme": {
|
|
35
|
+
"type": "string"
|
|
36
|
+
},
|
|
37
|
+
"scale": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"contrast": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"additionalProperties": {
|
|
45
|
+
"type": "string"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"tokenWithValue": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["name", "value"],
|
|
51
|
+
"not": {
|
|
52
|
+
"required": ["$ref"]
|
|
53
|
+
},
|
|
54
|
+
"properties": {
|
|
55
|
+
"specVersion": {
|
|
56
|
+
"const": "1.0.0-draft"
|
|
57
|
+
},
|
|
58
|
+
"name": {
|
|
59
|
+
"$ref": "#/$defs/nameObject"
|
|
60
|
+
},
|
|
61
|
+
"value": {
|
|
62
|
+
"description": "Literal value; type narrowed by value-type schemas where applicable.",
|
|
63
|
+
"anyOf": [
|
|
64
|
+
{
|
|
65
|
+
"$ref": "value-types/color.schema.json"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"type": "string"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"type": "number"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "boolean"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "object"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"type": "array"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
"uuid": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"format": "uuid"
|
|
87
|
+
},
|
|
88
|
+
"introduced": {
|
|
89
|
+
"type": "string"
|
|
90
|
+
},
|
|
91
|
+
"deprecated": {
|
|
92
|
+
"type": "boolean"
|
|
93
|
+
},
|
|
94
|
+
"deprecated_comment": {
|
|
95
|
+
"type": "string"
|
|
96
|
+
},
|
|
97
|
+
"status": {
|
|
98
|
+
"type": "string"
|
|
99
|
+
},
|
|
100
|
+
"renamed": {
|
|
101
|
+
"type": "string"
|
|
102
|
+
},
|
|
103
|
+
"private": {
|
|
104
|
+
"type": "boolean"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"additionalProperties": false
|
|
108
|
+
},
|
|
109
|
+
"tokenWithRef": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"required": ["name", "$ref"],
|
|
112
|
+
"not": {
|
|
113
|
+
"required": ["value"]
|
|
114
|
+
},
|
|
115
|
+
"properties": {
|
|
116
|
+
"specVersion": {
|
|
117
|
+
"const": "1.0.0-draft"
|
|
118
|
+
},
|
|
119
|
+
"name": {
|
|
120
|
+
"$ref": "#/$defs/nameObject"
|
|
121
|
+
},
|
|
122
|
+
"$ref": {
|
|
123
|
+
"type": "string",
|
|
124
|
+
"minLength": 1,
|
|
125
|
+
"description": "Alias target path or stable token id (resolution is Layer 2)."
|
|
126
|
+
},
|
|
127
|
+
"uuid": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"format": "uuid"
|
|
130
|
+
},
|
|
131
|
+
"introduced": {
|
|
132
|
+
"type": "string"
|
|
133
|
+
},
|
|
134
|
+
"deprecated": {
|
|
135
|
+
"type": "boolean"
|
|
136
|
+
},
|
|
137
|
+
"deprecated_comment": {
|
|
138
|
+
"type": "string"
|
|
139
|
+
},
|
|
140
|
+
"status": {
|
|
141
|
+
"type": "string"
|
|
142
|
+
},
|
|
143
|
+
"renamed": {
|
|
144
|
+
"type": "string"
|
|
145
|
+
},
|
|
146
|
+
"private": {
|
|
147
|
+
"type": "boolean"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"additionalProperties": false
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/value-types/color.schema.json",
|
|
4
|
+
"title": "Color value",
|
|
5
|
+
"description": "RGB or RGBA color string (aligned with legacy Spectrum token color pattern).",
|
|
6
|
+
"type": "string",
|
|
7
|
+
"pattern": "^rgba\\((([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]),\\s?){3}(0|1|0?\\.\\d+)\\)|rgb\\(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1,3}(,\\s?\\d{1,3}%?){2}\\)$"
|
|
8
|
+
}
|
package/spec/cascade.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Cascade resolution
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines the **cascade model**: three **layers**, **semantic specificity**, and the **resolution algorithm** used to pick a single winning token value for a given **context**.
|
|
6
|
+
|
|
7
|
+
## Layers
|
|
8
|
+
|
|
9
|
+
Design data is organized in three layers, ordered from lowest to highest precedence when values conflict:
|
|
10
|
+
|
|
11
|
+
| Layer | Name | Description |
|
|
12
|
+
| ----- | -------------- | ------------------------------------------------------------------------------------------- |
|
|
13
|
+
| 1 | **Foundation** | Canonical design system data (e.g. Spectrum foundation). |
|
|
14
|
+
| 2 | **Platform** | Platform-specific adjustments; **MUST** remain type-compatible with foundation. |
|
|
15
|
+
| 3 | **Product** | Product-specific overrides; **MUST** remain type-compatible with the resolved lower layers. |
|
|
16
|
+
|
|
17
|
+
**NORMATIVE:** When two candidates match the same context, the candidate from the **higher** layer (larger number above) **MUST** win.
|
|
18
|
+
|
|
19
|
+
**NORMATIVE:** Overrides **MUST NOT** change the resolved token’s **value type** (e.g. color alias cannot resolve to a non-color).
|
|
20
|
+
|
|
21
|
+
## Semantic specificity
|
|
22
|
+
|
|
23
|
+
**Specificity** counts how many **non-default** dimension fields in the token’s **name object** are set for the dimensions declared in the dataset.
|
|
24
|
+
|
|
25
|
+
**NORMATIVE:** Default dimension values (see [Dimensions](dimensions.md)) **MUST NOT** contribute to specificity.
|
|
26
|
+
|
|
27
|
+
**NORMATIVE:** When two candidates from the **same layer** match the context, the candidate with **higher** specificity **MUST** win.
|
|
28
|
+
|
|
29
|
+
**NORMATIVE:** Ties on layer and specificity **MUST** be broken by a deterministic **document order** rule defined by the manifest or dataset index (implementation-defined in this draft; validators **SHOULD** emit a warning on ambiguous ties).
|
|
30
|
+
|
|
31
|
+
## Context
|
|
32
|
+
|
|
33
|
+
A **resolution context** is a set of dimension key/value pairs (e.g. `colorScheme: dark`, `scale: medium`, `contrast: regular`) plus the **target layer** being resolved (usually product → platform → foundation).
|
|
34
|
+
|
|
35
|
+
## Resolution algorithm (informative outline)
|
|
36
|
+
|
|
37
|
+
The following outline is **RECOMMENDED** for conforming resolvers:
|
|
38
|
+
|
|
39
|
+
1. Collect all token candidates whose name object **matches** the context (every specified dimension in the context equals the name object’s dimension field, or the name object omits that dimension where omission means “matches any” per dimension rules).
|
|
40
|
+
2. Filter to candidates at or below the requested layer.
|
|
41
|
+
3. Select the maximum **layer** precedence.
|
|
42
|
+
4. Within that layer, select the maximum **specificity**.
|
|
43
|
+
5. Break remaining ties by deterministic ordering.
|
|
44
|
+
|
|
45
|
+
Exact matching rules for omitted dimensions are defined alongside dimension declarations in [Dimensions](dimensions.md).
|
|
46
|
+
|
|
47
|
+
## Cross-dimensional overrides
|
|
48
|
+
|
|
49
|
+
**NORMATIVE:** Overrides that combine multiple dimensions in a way not expressible by a single name object alone **MUST** use **explicit combination tokens** (tokens whose name object sets multiple non-default dimensions) as defined in the dataset; magic merging of unrelated tokens is **NOT** allowed.
|
|
50
|
+
|
|
51
|
+
## References
|
|
52
|
+
|
|
53
|
+
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
|
54
|
+
* [#714 — Design Data Specification](https://github.com/adobe/spectrum-design-data/discussions/714)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Dimensions
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines how **dimensions** (modes such as color scheme, scale, contrast) are **declared**, assigned **defaults**, and validated for **coverage**.
|
|
6
|
+
|
|
7
|
+
## Dimension declaration
|
|
8
|
+
|
|
9
|
+
A **dimension declaration** is a JSON object describing one axis of variation. It **MUST** conform to [`dimension.schema.json`](../schemas/dimension.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/dimension.schema.json`).
|
|
10
|
+
|
|
11
|
+
### Required fields
|
|
12
|
+
|
|
13
|
+
| Field | Description |
|
|
14
|
+
| --------- | --------------------------------------------------------- |
|
|
15
|
+
| `name` | Stable identifier for the dimension (e.g. `colorScheme`). |
|
|
16
|
+
| `modes` | Array of allowed mode values (strings). |
|
|
17
|
+
| `default` | Default mode; **MUST** be a member of `modes`. |
|
|
18
|
+
|
|
19
|
+
### Optional fields
|
|
20
|
+
|
|
21
|
+
| Field | Description |
|
|
22
|
+
| ------------- | ------------------------------------ |
|
|
23
|
+
| `description` | Human-readable documentation. |
|
|
24
|
+
| `coverage` | Rules for mode coverage (see below). |
|
|
25
|
+
|
|
26
|
+
## Built-in dimensions
|
|
27
|
+
|
|
28
|
+
These dimensions **SHOULD** be used consistently across Spectrum-compatible datasets:
|
|
29
|
+
|
|
30
|
+
| `name` | Typical `modes` | Notes |
|
|
31
|
+
| ------------- | ------------------------------- | ----------------------------- |
|
|
32
|
+
| `colorScheme` | `light`, `dark`, `wireframe`, … | Theme / appearance. |
|
|
33
|
+
| `scale` | `medium`, `large`, … | Density / t-shirt scale. |
|
|
34
|
+
| `contrast` | `regular`, `high`, … | Accessibility contrast level. |
|
|
35
|
+
|
|
36
|
+
## Optional dimensions
|
|
37
|
+
|
|
38
|
+
Additional dimensions (e.g. `language`, `motion`) **MAY** be declared in a dataset’s dimension catalog. Token name objects **MAY** include keys matching declared dimension names.
|
|
39
|
+
|
|
40
|
+
## Defaults and specificity
|
|
41
|
+
|
|
42
|
+
**NORMATIVE:** A token name object **omitting** a dimension field implies the token applies under the dimension’s **`default`** mode for specificity and matching purposes unless the spec for that dimension states otherwise.
|
|
43
|
+
|
|
44
|
+
**NORMATIVE:** Only **non-default** dimension fields on the name object increase **semantic specificity** (see [Cascade](cascade.md)).
|
|
45
|
+
|
|
46
|
+
## Coverage validation
|
|
47
|
+
|
|
48
|
+
**RECOMMENDED:** If a dimension’s `coverage` requires **peer modes** (e.g. defining `dark` requires `light`), validators implement rule **`SPEC-005`** (see `rules/rules.yaml`).
|
|
49
|
+
|
|
50
|
+
**RECOMMENDED:** Explicit **combination** tokens are used for rare cross-dimensional cases instead of inferring Cartesian products.
|
|
51
|
+
|
|
52
|
+
## References
|
|
53
|
+
|
|
54
|
+
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
|
55
|
+
* [#714 — Design Data Specification](https://github.com/adobe/spectrum-design-data/discussions/714)
|
package/spec/index.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Design Data Specification
|
|
2
|
+
|
|
3
|
+
**Version:** `1.0.0-draft`\
|
|
4
|
+
**Status:** Draft — normative text and schemas may change before `1.0.0`.
|
|
5
|
+
|
|
6
|
+
This document is the top-level overview for the **Design Data Specification**: a machine-readable model for Spectrum design tokens, dimensions, platform manifests, and validation.
|
|
7
|
+
|
|
8
|
+
## Scope
|
|
9
|
+
|
|
10
|
+
The specification defines:
|
|
11
|
+
|
|
12
|
+
1. **Token format** — structured token identity (`name`), literal `value` or alias `$ref`, and lifecycle metadata ([Token format](token-format.md)).
|
|
13
|
+
2. **Cascade and resolution** — layered data (foundation, platform, product), specificity, and how a context picks a winning value ([Cascade](cascade.md)).
|
|
14
|
+
3. **Dimensions** — declared modes, defaults, and coverage expectations ([Dimensions](dimensions.md)).
|
|
15
|
+
4. **Platform manifest** — how a platform repo pins foundation data, filters tokens, and applies typed overrides ([Manifest](manifest.md)).
|
|
16
|
+
|
|
17
|
+
Out of scope for this draft (tracked elsewhere):
|
|
18
|
+
|
|
19
|
+
* Exact query syntax for `include` / `exclude` in manifests (placeholder fields only).
|
|
20
|
+
* Full evolution, migration windows, and SDK version negotiation — see [discussion #735](https://github.com/adobe/spectrum-design-data/discussions/735).
|
|
21
|
+
|
|
22
|
+
## Conformance
|
|
23
|
+
|
|
24
|
+
The key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** in this specification are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) \[[RFC2119](https://www.rfc-editor.org/rfc/rfc2119.html)] \[[RFC8174](https://www.rfc-editor.org/rfc/rfc8174.html)] when, and only when, they appear in all capitals, as shown here.
|
|
25
|
+
|
|
26
|
+
### Conformance levels
|
|
27
|
+
|
|
28
|
+
| Level | Meaning |
|
|
29
|
+
| --------------- | ------------------------------------------------------- |
|
|
30
|
+
| **NORMATIVE** | Required for a conforming document or tool. |
|
|
31
|
+
| **RECOMMENDED** | Strong default; deviations SHOULD be documented. |
|
|
32
|
+
| **OPTIONAL** | May be omitted unless a feature explicitly requires it. |
|
|
33
|
+
|
|
34
|
+
### Validation layers
|
|
35
|
+
|
|
36
|
+
Conformance is checked in three layers (all under `@adobe/design-data-spec`):
|
|
37
|
+
|
|
38
|
+
| Layer | Artifact | Responsibility |
|
|
39
|
+
| ----- | ------------------ | ---------------------------------------------------------- |
|
|
40
|
+
| 1 | `schemas/*.json` | Per-instance structural shape (JSON Schema Draft 2020-12). |
|
|
41
|
+
| 2 | `rules/rules.yaml` | Semantic rules with stable IDs (e.g. `SPEC-001`). |
|
|
42
|
+
| 3 | `conformance/` | Fixtures and expected diagnostics for implementors. |
|
|
43
|
+
|
|
44
|
+
A **conforming validator** MUST implement Layer 1 for supported document types and SHOULD implement Layer 2 rules whose `introduced_in` is less than or equal to the validator’s claimed spec version.
|
|
45
|
+
|
|
46
|
+
## Spec version and SemVer
|
|
47
|
+
|
|
48
|
+
This document set carries the **spec version** `1.0.0-draft`. Published artifacts (schemas, rule catalog) are expected to align with [Semantic Versioning](https://semver.org/) once `1.0.0` is released: **MAJOR** for incompatible schema or rule behavior, **MINOR** for backward-compatible additions, **PATCH** for clarifications and compatible fixes.
|
|
49
|
+
|
|
50
|
+
Full governance (compatibility tiers, migration, CLI `--spec-version`) is discussed in [discussion #735 — Versioning and Evolution](https://github.com/adobe/spectrum-design-data/discussions/735).
|
|
51
|
+
|
|
52
|
+
## Normative references (sibling documents)
|
|
53
|
+
|
|
54
|
+
| Document | Role |
|
|
55
|
+
| ------------------------------- | ---------------------------------------------------------------- |
|
|
56
|
+
| [Token format](token-format.md) | Token `name`, `value` / `$ref`, value types, lifecycle metadata. |
|
|
57
|
+
| [Cascade](cascade.md) | Layers, specificity, resolution algorithm. |
|
|
58
|
+
| [Dimensions](dimensions.md) | Dimension declarations, built-in dimensions, coverage. |
|
|
59
|
+
| [Manifest](manifest.md) | Platform manifest fields and validation expectations. |
|
|
60
|
+
|
|
61
|
+
## JSON Schema `$id` and versioning
|
|
62
|
+
|
|
63
|
+
**NORMATIVE:** Canonical schema documents use **versioned path** `$id` URIs so major revisions can coexist on the documentation host:
|
|
64
|
+
|
|
65
|
+
* Base: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/`
|
|
66
|
+
* Examples: `.../v0/token.schema.json`, `.../v0/dimension.schema.json`, `.../v0/manifest.schema.json`
|
|
67
|
+
|
|
68
|
+
The **`v0`** segment denotes the **draft / pre-1.0** schema family aligned with spec version `1.0.0-draft`. A future **1.0.0** stable release MAY introduce `v1` paths without reusing `v0` URLs for incompatible shapes.
|
|
69
|
+
|
|
70
|
+
**RECOMMENDED:** Each root schema document includes a top-level string property `specVersion` (const matching this spec’s version label) when the instance is a design-data document that should self-identify; see individual schemas.
|
|
71
|
+
|
|
72
|
+
Packaged copies in this repository live under `packages/design-data-spec/schemas/`; their `$id` still identifies the canonical published URL above.
|
|
73
|
+
|
|
74
|
+
## Relationship to existing Adobe packages
|
|
75
|
+
|
|
76
|
+
| Package / area | Relationship |
|
|
77
|
+
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
78
|
+
| `@adobe/spectrum-tokens` | **Current** token JSON under `packages/tokens/` is the **legacy** shape (e.g. `color-set`, `scale-set`). This spec defines the **target** format; backward-compat schemas and migration are Phase 1 ([#723](https://github.com/adobe/spectrum-design-data/issues/723)). |
|
|
79
|
+
| `@adobe/design-system-registry` | Registry enums and component metadata MAY be referenced by validation rules (e.g. component association); exact coupling is Layer 2. |
|
|
80
|
+
| `@adobe/spectrum-component-api-schemas` | Component schemas MAY be cross-checked by graph rules; not required for Layer 1 structural validation. |
|
|
81
|
+
|
|
82
|
+
## Umbrella discussions
|
|
83
|
+
|
|
84
|
+
* [#714 — Design Data Specification (umbrella)](https://github.com/adobe/spectrum-design-data/discussions/714)
|
|
85
|
+
* [#715 — Distributed Design Data Architecture](https://github.com/adobe/spectrum-design-data/discussions/715)
|
|
86
|
+
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
package/spec/manifest.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Platform manifest
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines the **platform manifest**: how a platform implementation repository declares its relationship to **foundation** design data — version pin, inclusion filters, typed overrides, and extensions.
|
|
6
|
+
|
|
7
|
+
## Manifest document
|
|
8
|
+
|
|
9
|
+
A manifest **MUST** conform to [`manifest.schema.json`](../schemas/manifest.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/manifest.schema.json`).
|
|
10
|
+
|
|
11
|
+
## Required fields
|
|
12
|
+
|
|
13
|
+
| Field | Type | Description |
|
|
14
|
+
| ------------------- | ------ | ------------------------------------------------------------- |
|
|
15
|
+
| `specVersion` | string | **MUST** be `1.0.0-draft` for documents targeting this draft. |
|
|
16
|
+
| `foundationVersion` | string | Pin to a released foundation version (semver or tag string). |
|
|
17
|
+
|
|
18
|
+
## Optional fields
|
|
19
|
+
|
|
20
|
+
| Field | Type | Description |
|
|
21
|
+
| ------------ | --------------- | -------------------------------------------------------------------------------- |
|
|
22
|
+
| `include` | array of string | Semantic **queries** selecting subsets of foundation tokens to materialize. |
|
|
23
|
+
| `exclude` | array of string | Queries removing tokens from the included set. |
|
|
24
|
+
| `overrides` | array of object | Typed overrides; each entry **MUST** preserve the target token’s **value type**. |
|
|
25
|
+
| `extensions` | object | New tokens or dimensions introduced at the platform layer. |
|
|
26
|
+
|
|
27
|
+
### `include` / `exclude`
|
|
28
|
+
|
|
29
|
+
**NORMATIVE:** Entries **MUST** be non-empty strings. The **query language** is **not** normative in `1.0.0-draft`; treat values as opaque identifiers for tooling until a future spec version defines syntax.
|
|
30
|
+
|
|
31
|
+
### `overrides`
|
|
32
|
+
|
|
33
|
+
Each override object **MUST** include enough information to identify a target token and supply a replacement **value** or **$ref** compatible with the target’s type.
|
|
34
|
+
|
|
35
|
+
**NORMATIVE:** Overrides **MUST NOT** change the resolved type of the token (aligns with [Cascade — type safety](cascade.md)).
|
|
36
|
+
|
|
37
|
+
### `extensions`
|
|
38
|
+
|
|
39
|
+
**RECOMMENDED:** `extensions` follows the same structural conventions as foundation token files (tokens, dimensions) and **SHOULD** be validated with the same Layer 1 and Layer 2 rules.
|
|
40
|
+
|
|
41
|
+
## Validation
|
|
42
|
+
|
|
43
|
+
**NORMATIVE:** Manifests **MUST** pass Layer 1 JSON Schema validation.
|
|
44
|
+
|
|
45
|
+
**RECOMMENDED:** Validators resolve `foundationVersion` against a registry or lockfile and report mismatches as errors or warnings per product policy.
|
|
46
|
+
|
|
47
|
+
## Automated upgrades
|
|
48
|
+
|
|
49
|
+
**OPTIONAL:** Workflows **MAY** open upgrade PRs when `foundationVersion` lags the latest release; details are out of scope for this document (see [#715](https://github.com/adobe/spectrum-design-data/discussions/715)).
|
|
50
|
+
|
|
51
|
+
## References
|
|
52
|
+
|
|
53
|
+
* [#715 — Distributed Design Data Architecture](https://github.com/adobe/spectrum-design-data/discussions/715)
|
|
54
|
+
* [#625 — Token Authoring Workflow](https://github.com/adobe/spectrum-design-data/discussions/625)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Token format
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines the normative **token** object: identity (`name`), either a literal **value** or an alias **`$ref`**, optional **metadata**, and **value types** validated by JSON Schema.
|
|
6
|
+
|
|
7
|
+
## Token object
|
|
8
|
+
|
|
9
|
+
A **token** is a JSON object that satisfies the Layer 1 schema [`token.schema.json`](../schemas/token.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/token.schema.json`).
|
|
10
|
+
|
|
11
|
+
### Required shape
|
|
12
|
+
|
|
13
|
+
A token **MUST** contain:
|
|
14
|
+
|
|
15
|
+
1. **`name`** — a JSON object (the **name object**) as defined below.
|
|
16
|
+
2. Exactly one of:
|
|
17
|
+
* **`value`** — a literal token value (type depends on value-type schema), or
|
|
18
|
+
* **`$ref`** — a string reference to another token (alias).
|
|
19
|
+
|
|
20
|
+
A token **MUST NOT** include both `value` and `$ref`.
|
|
21
|
+
|
|
22
|
+
### Name object
|
|
23
|
+
|
|
24
|
+
The **name object** identifies the token in a structured way. Implementations use it for cascade matching, specificity, and tooling.
|
|
25
|
+
|
|
26
|
+
**NORMATIVE fields** (all string unless noted):
|
|
27
|
+
|
|
28
|
+
| Field | Status | Description |
|
|
29
|
+
| --------------- | -------- | ----------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `property` | REQUIRED | Stable property key (e.g. semantic role of the token). |
|
|
31
|
+
| `component` | OPTIONAL | Component name when the token is component-scoped. |
|
|
32
|
+
| `variant` | OPTIONAL | Variant within a component. |
|
|
33
|
+
| `state` | OPTIONAL | Interactive or semantic state. |
|
|
34
|
+
| `colorScheme` | OPTIONAL | Dimension: light / dark / wireframe / etc. |
|
|
35
|
+
| `scale` | OPTIONAL | Dimension: t-shirt size or density scale. |
|
|
36
|
+
| `contrast` | OPTIONAL | Dimension: contrast level. |
|
|
37
|
+
| Additional keys | OPTIONAL | Other dimensions declared in the dataset’s dimension catalog (see [Dimensions](dimensions.md)). |
|
|
38
|
+
|
|
39
|
+
**RECOMMENDED:** Name objects use a consistent key ordering in authored files for diffs; this is not a conformance requirement.
|
|
40
|
+
|
|
41
|
+
### Alias (`$ref`)
|
|
42
|
+
|
|
43
|
+
When **`$ref`** is present, the token is an **alias**. The value **MUST** be a non-empty string interpreted as a **token path** or **stable identifier** resolvable by the validator (resolution rules are Layer 2; see rule `SPEC-001` in `rules/rules.yaml`).
|
|
44
|
+
|
|
45
|
+
### Literal `value`
|
|
46
|
+
|
|
47
|
+
When **`value`** is present, it **MUST** conform to the declared value type for that token. Value types are defined under `schemas/value-types/` and referenced from the token schema.
|
|
48
|
+
|
|
49
|
+
### Lifecycle and metadata
|
|
50
|
+
|
|
51
|
+
The following OPTIONAL fields align with token lifecycle discussions (e.g. [#623](https://github.com/adobe/spectrum-design-data/discussions/623)):
|
|
52
|
+
|
|
53
|
+
| Field | Type | Description |
|
|
54
|
+
| -------------------- | ------------- | ----------------------------------------------- |
|
|
55
|
+
| `uuid` | string (UUID) | Stable unique id for rename tracking and diffs. |
|
|
56
|
+
| `introduced` | string | Version or date token was introduced. |
|
|
57
|
+
| `deprecated` | boolean | Marked deprecated. |
|
|
58
|
+
| `deprecated_comment` | string | Human-readable deprecation note. |
|
|
59
|
+
| `status` | string | e.g. `experimental`, `stable`. |
|
|
60
|
+
| `renamed` | string | Previous name or id if renamed. |
|
|
61
|
+
| `private` | boolean | Not part of public API surface. |
|
|
62
|
+
|
|
63
|
+
**NORMATIVE:** If `deprecated` is `true`, `deprecated_comment` **SHOULD** be present.
|
|
64
|
+
|
|
65
|
+
### `specVersion`
|
|
66
|
+
|
|
67
|
+
**RECOMMENDED:** Root token documents (when stored as standalone JSON files) include `specVersion` with const `1.0.0-draft` for self-identification. Embedded tokens inside larger files **MAY** omit it if the parent document carries version metadata.
|
|
68
|
+
|
|
69
|
+
## Value types
|
|
70
|
+
|
|
71
|
+
Individual types (color, dimension, opacity, etc.) **MUST** be defined as JSON Schemas under `schemas/value-types/` and **MUST** use `$id` under the same `v0` base path as [Overview — JSON Schema `$id`](index.md).
|
|
72
|
+
|
|
73
|
+
## Relationship to legacy Spectrum tokens
|
|
74
|
+
|
|
75
|
+
The current `@adobe/spectrum-tokens` JSON uses **sets** (`color-set`, `scale-set`, …). This specification describes the **target** per-token model. Mapping from legacy to this format is out of scope for this document; see [#723](https://github.com/adobe/spectrum-design-data/issues/723).
|
|
76
|
+
|
|
77
|
+
## References
|
|
78
|
+
|
|
79
|
+
* [#646 — Token Schema Structure and Validation System](https://github.com/adobe/spectrum-design-data/discussions/646)
|
|
80
|
+
* [#623 — Token Lifecycle Metadata](https://github.com/adobe/spectrum-design-data/discussions/623)
|