@adobe/design-data-spec 2.8.0 → 3.0.0
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/conformance/invalid/SPEC-022/dataset.json +1 -1
- package/conformance/invalid/SPEC-037/dataset.json +1 -1
- package/conformance/invalid/SPEC-043/dataset.json +1 -1
- package/conformance/invalid/SPEC-049/dataset.json +13 -0
- package/conformance/invalid/SPEC-049/expected-errors.json +10 -0
- package/conformance/query/and-conditions/input/tokens.tokens.json +2 -2
- package/conformance/query/and-or-precedence/input/tokens.tokens.json +4 -4
- package/conformance/valid/SPEC-025/dataset.json +17 -0
- package/conformance/valid/SPEC-037/dataset.json +2 -2
- package/conformance/valid/SPEC-049/dataset.json +43 -0
- package/conformance/valid/component-refs/dataset.json +1 -1
- package/package.json +1 -1
- package/rules/rules.yaml +20 -2
- package/schemas/field.schema.json +1 -1
- package/schemas/registry-value.json +4 -0
- package/schemas/state-declaration.schema.json +1 -1
- package/schemas/token.schema.json +7 -2
- package/spec/query.md +4 -0
- package/spec/state-model.md +2 -2
- package/spec/token-format.md +20 -20
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"name": { "property": "bg", "component": "button", "state": "hover" },
|
|
3
|
+
"name": { "property": "bg", "component": "button", "state": ["hover"] },
|
|
4
4
|
"value": "#aaaaaa",
|
|
5
5
|
"uuid": "aaaaaaaa-0001-4000-8000-000000000001"
|
|
6
6
|
},
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"uuid": "aaaaaaaa-0002-4000-8000-000000000001"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
"name": { "property": "bg", "component": "checkbox", "state": "hover" },
|
|
13
|
+
"name": { "property": "bg", "component": "checkbox", "state": ["hover"] },
|
|
14
14
|
"value": "#cccccc",
|
|
15
15
|
"uuid": "aaaaaaaa-0003-4000-8000-000000000001"
|
|
16
16
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"name": { "property": "bg", "component": "button", "state": "hover" },
|
|
3
|
+
"name": { "property": "bg", "component": "button", "state": ["hover"] },
|
|
4
4
|
"value": "#aaaaaa",
|
|
5
5
|
"uuid": "aaaaaaaa-0001-4000-8000-000000000001"
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
|
-
"name": { "property": "bg", "component": "button", "state": "default" },
|
|
8
|
+
"name": { "property": "bg", "component": "button", "state": ["default"] },
|
|
9
9
|
"value": "#bbbbbb",
|
|
10
10
|
"uuid": "aaaaaaaa-0002-4000-8000-000000000001"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
"name": { "property": "bg", "component": "checkbox", "state": "default" },
|
|
13
|
+
"name": { "property": "bg", "component": "checkbox", "state": ["default"] },
|
|
14
14
|
"value": "#cccccc",
|
|
15
15
|
"uuid": "aaaaaaaa-0003-4000-8000-000000000001"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"name": { "property": "bg", "component": "slider", "state": "hover" },
|
|
18
|
+
"name": { "property": "bg", "component": "slider", "state": ["hover"] },
|
|
19
19
|
"value": "#dddddd",
|
|
20
20
|
"uuid": "aaaaaaaa-0004-4000-8000-000000000001"
|
|
21
21
|
}
|
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
"property": "color"
|
|
8
8
|
},
|
|
9
9
|
"value": "#ffffff"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": {
|
|
13
|
+
"structure": "accessory",
|
|
14
|
+
"anatomy": "item",
|
|
15
|
+
"property": "padding",
|
|
16
|
+
"size": "small",
|
|
17
|
+
"legacyKey": "accessory-item-padding-small"
|
|
18
|
+
},
|
|
19
|
+
"value": "4px"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": {
|
|
23
|
+
"anatomy": "focus-ring",
|
|
24
|
+
"property": "gap"
|
|
25
|
+
},
|
|
26
|
+
"value": "2px"
|
|
10
27
|
}
|
|
11
28
|
],
|
|
12
29
|
"components": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{
|
|
21
21
|
"name": {
|
|
22
22
|
"component": "button",
|
|
23
|
-
"state": "hover",
|
|
23
|
+
"state": ["hover"],
|
|
24
24
|
"property": "background-color"
|
|
25
25
|
},
|
|
26
26
|
"value": "#eeeeee"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
{
|
|
29
29
|
"name": {
|
|
30
30
|
"component": "button",
|
|
31
|
-
"state": "pressed",
|
|
31
|
+
"state": ["pressed"],
|
|
32
32
|
"property": "background-color"
|
|
33
33
|
},
|
|
34
34
|
"value": "#cccccc",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tokens": [
|
|
3
|
+
{
|
|
4
|
+
"name": {
|
|
5
|
+
"structure": "accessory",
|
|
6
|
+
"anatomy": "item",
|
|
7
|
+
"property": "padding",
|
|
8
|
+
"size": "small",
|
|
9
|
+
"legacyKey": "accessory-item-padding-small"
|
|
10
|
+
},
|
|
11
|
+
"value": "4px"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": {
|
|
15
|
+
"anatomy": "focus-ring",
|
|
16
|
+
"property": "gap"
|
|
17
|
+
},
|
|
18
|
+
"value": "2px"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": {
|
|
22
|
+
"component": "button",
|
|
23
|
+
"anatomy": "wibble",
|
|
24
|
+
"property": "color"
|
|
25
|
+
},
|
|
26
|
+
"value": "#ffffff"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"components": [
|
|
30
|
+
{
|
|
31
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/button.json",
|
|
32
|
+
"name": "button",
|
|
33
|
+
"displayName": "Button",
|
|
34
|
+
"meta": {
|
|
35
|
+
"category": "actions",
|
|
36
|
+
"documentationUrl": "https://spectrum.adobe.com/page/button/"
|
|
37
|
+
},
|
|
38
|
+
"anatomy": [
|
|
39
|
+
{ "name": "wibble", "description": "Custom documented part." }
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
package/package.json
CHANGED
package/rules/rules.yaml
CHANGED
|
@@ -223,8 +223,12 @@ rules:
|
|
|
223
223
|
name: anatomy-requires-component
|
|
224
224
|
severity: error
|
|
225
225
|
category: reference-integrity
|
|
226
|
-
assert:
|
|
227
|
-
|
|
226
|
+
assert: >
|
|
227
|
+
A token name object MUST NOT include an 'anatomy' field unless a 'component' or
|
|
228
|
+
'structure' field is also present, or the 'anatomy' value is a registry term
|
|
229
|
+
flagged 'standaloneScope: true' in anatomy-terms.json (cross-cutting parts with
|
|
230
|
+
no single owning component, e.g. 'focus-ring', 'focus-indicator').
|
|
231
|
+
message: "Token '{token}' has 'anatomy' field without a 'component' or 'structure' field, and '{anatomy}' is not a registry term flagged standaloneScope"
|
|
228
232
|
spec_ref: spec/anatomy-format.md#cross-reference-with-token-name-objects
|
|
229
233
|
introduced_in: "1.0.0-draft"
|
|
230
234
|
|
|
@@ -560,3 +564,17 @@ rules:
|
|
|
560
564
|
message: "Anatomy part '{part}' on component '{component}' contains '{child}', which is not a declared anatomy part on this component"
|
|
561
565
|
spec_ref: spec/anatomy-format.md#contains
|
|
562
566
|
introduced_in: "1.0.0-draft"
|
|
567
|
+
|
|
568
|
+
- id: SPEC-049
|
|
569
|
+
name: anatomy-in-registry
|
|
570
|
+
severity: error
|
|
571
|
+
layer: 2
|
|
572
|
+
category: reference-integrity
|
|
573
|
+
assert: >
|
|
574
|
+
A token name-object 'anatomy' field with no 'component' (SPEC-020 validates that
|
|
575
|
+
case) MUST reference a known id in the anatomy-terms.json registry. Backstops the
|
|
576
|
+
two cases SPEC-025 allows anatomy without a component: 'structure'-scoped anatomy
|
|
577
|
+
and registry terms flagged 'standaloneScope: true'.
|
|
578
|
+
message: "Token '{token}' references anatomy part '{anatomy}' which is not in the spectrum-design-data registry/anatomy-terms vocabulary"
|
|
579
|
+
spec_ref: spec/anatomy-format.md#cross-reference-with-token-name-objects
|
|
580
|
+
introduced_in: "1.0.0-draft"
|
|
@@ -66,6 +66,10 @@
|
|
|
66
66
|
"type": "boolean",
|
|
67
67
|
"description": "Whether this value is deprecated"
|
|
68
68
|
},
|
|
69
|
+
"standaloneScope": {
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"description": "Anatomy-term only: whether this term may scope a token's name object on its own, without an accompanying component or structure field (e.g. cross-cutting parts like focus-ring/focus-indicator that have no single owner)"
|
|
72
|
+
},
|
|
69
73
|
"usedIn": {
|
|
70
74
|
"type": "array",
|
|
71
75
|
"description": "Where this value is used (tokens, component-schemas, etc.)",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"type": "string",
|
|
11
11
|
"pattern": "^[a-z][a-z0-9-]*$",
|
|
12
12
|
"minLength": 1,
|
|
13
|
-
"description": "Kebab-case state identifier. Must match
|
|
13
|
+
"description": "Kebab-case state identifier. Must match an element of the token name-object 'state' array."
|
|
14
14
|
},
|
|
15
15
|
"description": {
|
|
16
16
|
"type": "string",
|
|
@@ -48,8 +48,13 @@
|
|
|
48
48
|
"description": "Semantic: variant within a component (e.g. accent, negative, primary)."
|
|
49
49
|
},
|
|
50
50
|
"state": {
|
|
51
|
-
"type": "
|
|
52
|
-
"
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
55
|
+
},
|
|
56
|
+
"minItems": 1,
|
|
57
|
+
"description": "Semantic: interactive or semantic state, as an ordered array of atomic state ids (e.g. [\"hover\"], [\"selected\", \"hover\"])."
|
|
53
58
|
},
|
|
54
59
|
"qualifier": {
|
|
55
60
|
"type": "string",
|
package/spec/query.md
CHANGED
|
@@ -77,6 +77,10 @@ The expression `a=x,b=y|c=z` is equivalent to `(a=x AND b=y) OR (c=z)`.
|
|
|
77
77
|
|
|
78
78
|
**RATIONALE:** Negation matching absent fields follows the convention that "not equal to X" includes "does not exist" — the same semantics as label selectors in Kubernetes and CSS attribute selectors.
|
|
79
79
|
|
|
80
|
+
**NORMATIVE:** `state` (and any future array-valued key) resolves to each element of the array individually. For equality (`=`), a condition matches when **any** element equals the specified value. For negation (`!=`), a condition matches when **no** element equals the specified value (or the field is absent). For example, a token with `name.state: ["selected", "hover"]` matches `state=hover` and does **not** match `state!=hover`.
|
|
81
|
+
|
|
82
|
+
**RATIONALE:** A compound state (Proposal 006) represents a token that is simultaneously in multiple states; querying for one of those states should find it, consistent with treating the array as a set of active states rather than requiring an exact-array match.
|
|
83
|
+
|
|
80
84
|
## Glob matching
|
|
81
85
|
|
|
82
86
|
**NORMATIVE:** The `*` character in a value is a **glob wildcard** matching zero or more characters.
|
package/spec/state-model.md
CHANGED
|
@@ -10,7 +10,7 @@ Scoped under [RFC-A — Component Contract in Design Data Spec](https://github.c
|
|
|
10
10
|
|
|
11
11
|
A **component state** is a named condition under which a component's visual presentation differs from its baseline. States drive token resolution: when a component is in a given state, the design system selects tokens scoped to that state name rather than (or layered on top of) the baseline tokens.
|
|
12
12
|
|
|
13
|
-
State names appear in the `state` field of token name objects (see [Token format — Name object](token-format.md#name-object)). A token with `"state": "hover"` applies only when the component is in the `hover` state. For this cross-reference to be machine-enforceable, state declarations **MUST** be present on the component declaration.
|
|
13
|
+
State names appear in the `state` field of token name objects, an ordered array of one or more atomic state ids (see [Token format — Name object](token-format.md#name-object) and [Proposal 006](../../../docs/proposals/006-compound-states-as-array.md)). A token with `"state": ["hover"]` applies only when the component is in the `hover` state; `"state": ["selected", "hover"]` applies when both states are simultaneously active. For this cross-reference to be machine-enforceable, state declarations **MUST** be present on the component declaration.
|
|
14
14
|
|
|
15
15
|
States fall into two trigger types:
|
|
16
16
|
|
|
@@ -188,7 +188,7 @@ See [Token format — Name object](token-format.md#name-object) for the full nam
|
|
|
188
188
|
"component": "checkbox",
|
|
189
189
|
"anatomy": "checkmark",
|
|
190
190
|
"property": "color",
|
|
191
|
-
"state": "selected"
|
|
191
|
+
"state": ["selected"]
|
|
192
192
|
},
|
|
193
193
|
"value": "#0265dc"
|
|
194
194
|
}
|
package/spec/token-format.md
CHANGED
|
@@ -55,25 +55,25 @@ The table below lists all semantic fields. Fields marked with a scope are domain
|
|
|
55
55
|
|
|
56
56
|
**Universal semantic fields** (`scope: null` — apply to all token types):
|
|
57
57
|
|
|
58
|
-
| Field | Status | Taxonomy category | Description
|
|
59
|
-
| -------------- | -------- | ----------------- |
|
|
60
|
-
| `property` | REQUIRED | Property | The stylistic attribute being defined (e.g. `color`, `width`, `padding`, `gap`).
|
|
61
|
-
| `component` | OPTIONAL | Component | Component name when the token is component-scoped.
|
|
62
|
-
| `structure` | OPTIONAL | Structure | Reusable visual pattern or object category (e.g. `base`, `container`, `list`, `accessory`). Distinct from `component`.
|
|
63
|
-
| `substructure` | OPTIONAL | Sub-structure | A structure that only exists within its parent structure (e.g. `item` in `list-item`).
|
|
64
|
-
| `anatomy` | OPTIONAL | Anatomy | A visible, named part of a component as defined by designers (e.g. `handle`, `icon`, `label`). See [Taxonomy — Component anatomy](taxonomy.md#component-anatomy).
|
|
65
|
-
| `object` | OPTIONAL | Object | Styling surface to which a visual property is applied (e.g. `background`, `border`, `edge`). See [Taxonomy — Token objects](taxonomy.md#token-objects-styling-surfaces).
|
|
66
|
-
| `variant` | OPTIONAL | Variant | Variant within a component (e.g. `accent`, `negative`, `primary`).
|
|
67
|
-
| `state` | OPTIONAL | State |
|
|
68
|
-
| `orientation` | OPTIONAL | Orientation | Direction or order of structures and elements (e.g. `vertical`, `horizontal`).
|
|
69
|
-
| `position` | OPTIONAL | Position | Location of an object relative to another (e.g. `affixed`).
|
|
70
|
-
| `size` | OPTIONAL | Size | Relative t-shirt sizing for relationships across tokens (e.g. `small`, `medium`, `large`).
|
|
71
|
-
| `density` | OPTIONAL | Density | Space within or around component parts (e.g. `spacious`, `compact`).
|
|
72
|
-
| `shape` | OPTIONAL | Shape | Relative to overall component shape (e.g. `uniform`).
|
|
73
|
-
| `role` | OPTIONAL | Role | An object's role within a nesting relationship (e.g. `container`, `control`), distinct from `size`.
|
|
74
|
-
| `scaleIndex` | OPTIONAL | — | Numeric scale index appended at the end of the serialized name (e.g. `100`, `200`, `900`). Used by color palette, spacing, font-size, and motion duration tokens.
|
|
75
|
-
| `from` | OPTIONAL | — | Starting endpoint of a `space-between` measurement (e.g. `top`, `edge`, `text`). See [Space-between endpoints](#space-between-endpoints).
|
|
76
|
-
| `to` | OPTIONAL | — | Ending endpoint of a `space-between` measurement (e.g. `text`, `visual`, `control`). See [Space-between endpoints](#space-between-endpoints).
|
|
58
|
+
| Field | Status | Taxonomy category | Description |
|
|
59
|
+
| -------------- | -------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `property` | REQUIRED | Property | The stylistic attribute being defined (e.g. `color`, `width`, `padding`, `gap`). |
|
|
61
|
+
| `component` | OPTIONAL | Component | Component name when the token is component-scoped. |
|
|
62
|
+
| `structure` | OPTIONAL | Structure | Reusable visual pattern or object category (e.g. `base`, `container`, `list`, `accessory`). Distinct from `component`. |
|
|
63
|
+
| `substructure` | OPTIONAL | Sub-structure | A structure that only exists within its parent structure (e.g. `item` in `list-item`). |
|
|
64
|
+
| `anatomy` | OPTIONAL | Anatomy | A visible, named part of a component as defined by designers (e.g. `handle`, `icon`, `label`). See [Taxonomy — Component anatomy](taxonomy.md#component-anatomy). |
|
|
65
|
+
| `object` | OPTIONAL | Object | Styling surface to which a visual property is applied (e.g. `background`, `border`, `edge`). See [Taxonomy — Token objects](taxonomy.md#token-objects-styling-surfaces). |
|
|
66
|
+
| `variant` | OPTIONAL | Variant | Variant within a component (e.g. `accent`, `negative`, `primary`). |
|
|
67
|
+
| `state` | OPTIONAL | State | Ordered array of one or more interactive or semantic states (e.g. `["hover"]`, `["selected", "hover"]`). See [Proposal 006](../../../docs/proposals/006-compound-states-as-array.md). |
|
|
68
|
+
| `orientation` | OPTIONAL | Orientation | Direction or order of structures and elements (e.g. `vertical`, `horizontal`). |
|
|
69
|
+
| `position` | OPTIONAL | Position | Location of an object relative to another (e.g. `affixed`). |
|
|
70
|
+
| `size` | OPTIONAL | Size | Relative t-shirt sizing for relationships across tokens (e.g. `small`, `medium`, `large`). |
|
|
71
|
+
| `density` | OPTIONAL | Density | Space within or around component parts (e.g. `spacious`, `compact`). |
|
|
72
|
+
| `shape` | OPTIONAL | Shape | Relative to overall component shape (e.g. `uniform`). |
|
|
73
|
+
| `role` | OPTIONAL | Role | An object's role within a nesting relationship (e.g. `container`, `control`), distinct from `size`. |
|
|
74
|
+
| `scaleIndex` | OPTIONAL | — | Numeric scale index appended at the end of the serialized name (e.g. `100`, `200`, `900`). Used by color palette, spacing, font-size, and motion duration tokens. |
|
|
75
|
+
| `from` | OPTIONAL | — | Starting endpoint of a `space-between` measurement (e.g. `top`, `edge`, `text`). See [Space-between endpoints](#space-between-endpoints). |
|
|
76
|
+
| `to` | OPTIONAL | — | Ending endpoint of a `space-between` measurement (e.g. `text`, `visual`, `control`). See [Space-between endpoints](#space-between-endpoints). |
|
|
77
77
|
|
|
78
78
|
#### Space-between endpoints
|
|
79
79
|
|
|
@@ -122,7 +122,7 @@ When **`$ref`** is present, the token is an **alias**. The value **MUST** be a n
|
|
|
122
122
|
|
|
123
123
|
```json
|
|
124
124
|
// Cascade canonical form (recommended) — the UUID is stable across renames.
|
|
125
|
-
{ "name": { "property": "accent-background-color", "state": "default", "colorScheme": "dark" },
|
|
125
|
+
{ "name": { "property": "accent-background-color", "state": ["default"], "colorScheme": "dark" },
|
|
126
126
|
"$schema": "…/alias.json",
|
|
127
127
|
"$ref": "87a2c8f0-54fd-4939-8f42-3124fde1e49e",
|
|
128
128
|
"uuid": "f24eb871-6419-4cef-88a2-cca8548ae31e" }
|