@adobe/design-data-spec 0.14.0 → 0.15.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-037/dataset.json +78 -0
- package/conformance/invalid/SPEC-037/expected-errors.json +20 -0
- package/conformance/valid/SPEC-037/dataset.json +107 -0
- package/package.json +1 -1
- package/rules/rules.yaml +15 -0
- package/schemas/anatomy-part.schema.json +4 -0
- package/schemas/component.schema.json +16 -0
- package/schemas/state-declaration.schema.json +4 -0
- package/spec/anatomy-format.md +14 -0
- package/spec/component-format.md +43 -21
- package/spec/state-model.md +18 -4
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tokens": [
|
|
3
|
+
{
|
|
4
|
+
"name": {
|
|
5
|
+
"component": "slider",
|
|
6
|
+
"anatomy": "handle",
|
|
7
|
+
"property": "background-color"
|
|
8
|
+
},
|
|
9
|
+
"value": "#0265dc"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": {
|
|
13
|
+
"component": "button",
|
|
14
|
+
"state": "pressed",
|
|
15
|
+
"property": "background-color"
|
|
16
|
+
},
|
|
17
|
+
"value": "#cccccc"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": {
|
|
21
|
+
"component": "button",
|
|
22
|
+
"variant": "cta",
|
|
23
|
+
"property": "background-color"
|
|
24
|
+
},
|
|
25
|
+
"value": "#0265dc"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"components": [
|
|
29
|
+
{
|
|
30
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/slider.json",
|
|
31
|
+
"name": "slider",
|
|
32
|
+
"displayName": "Slider",
|
|
33
|
+
"meta": {
|
|
34
|
+
"category": "forms",
|
|
35
|
+
"documentationUrl": "https://spectrum.adobe.com/page/slider/"
|
|
36
|
+
},
|
|
37
|
+
"anatomy": [
|
|
38
|
+
{
|
|
39
|
+
"name": "handle",
|
|
40
|
+
"lifecycle": {
|
|
41
|
+
"deprecated": "1.0.0-draft",
|
|
42
|
+
"deprecatedComment": "Renamed to thumb."
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/button.json",
|
|
49
|
+
"name": "button",
|
|
50
|
+
"displayName": "Button",
|
|
51
|
+
"meta": {
|
|
52
|
+
"category": "actions",
|
|
53
|
+
"documentationUrl": "https://spectrum.adobe.com/page/button/"
|
|
54
|
+
},
|
|
55
|
+
"states": [
|
|
56
|
+
{
|
|
57
|
+
"name": "pressed",
|
|
58
|
+
"lifecycle": {
|
|
59
|
+
"deprecated": "1.0.0-draft",
|
|
60
|
+
"deprecatedComment": "Use active instead."
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"options": {
|
|
65
|
+
"variant": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"enum": ["primary", "secondary", "cta"],
|
|
68
|
+
"deprecatedEnumValues": {
|
|
69
|
+
"cta": {
|
|
70
|
+
"deprecated": "1.0.0-draft",
|
|
71
|
+
"deprecatedComment": "Use primary instead."
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"layer": 2,
|
|
3
|
+
"errors": [
|
|
4
|
+
{
|
|
5
|
+
"rule_id": "SPEC-037",
|
|
6
|
+
"severity": "warning",
|
|
7
|
+
"message_pattern": ".*deprecated anatomy part.*"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"rule_id": "SPEC-037",
|
|
11
|
+
"severity": "warning",
|
|
12
|
+
"message_pattern": ".*deprecated state.*"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"rule_id": "SPEC-037",
|
|
16
|
+
"severity": "warning",
|
|
17
|
+
"message_pattern": ".*deprecated option value.*"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tokens": [
|
|
3
|
+
{
|
|
4
|
+
"name": {
|
|
5
|
+
"component": "slider",
|
|
6
|
+
"anatomy": "track",
|
|
7
|
+
"property": "background-color"
|
|
8
|
+
},
|
|
9
|
+
"value": "#e0e0e0"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": {
|
|
13
|
+
"component": "slider",
|
|
14
|
+
"anatomy": "handle",
|
|
15
|
+
"property": "background-color"
|
|
16
|
+
},
|
|
17
|
+
"value": "#0265dc",
|
|
18
|
+
"deprecated": "1.0.0-draft"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": {
|
|
22
|
+
"component": "button",
|
|
23
|
+
"state": "hover",
|
|
24
|
+
"property": "background-color"
|
|
25
|
+
},
|
|
26
|
+
"value": "#eeeeee"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": {
|
|
30
|
+
"component": "button",
|
|
31
|
+
"state": "pressed",
|
|
32
|
+
"property": "background-color"
|
|
33
|
+
},
|
|
34
|
+
"value": "#cccccc",
|
|
35
|
+
"deprecated": "1.0.0-draft"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": {
|
|
39
|
+
"component": "button",
|
|
40
|
+
"variant": "primary",
|
|
41
|
+
"property": "background-color"
|
|
42
|
+
},
|
|
43
|
+
"value": "#0265dc"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": {
|
|
47
|
+
"component": "button",
|
|
48
|
+
"variant": "cta",
|
|
49
|
+
"property": "background-color"
|
|
50
|
+
},
|
|
51
|
+
"value": "#0265dc",
|
|
52
|
+
"deprecated": "1.0.0-draft"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"components": [
|
|
56
|
+
{
|
|
57
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/slider.json",
|
|
58
|
+
"name": "slider",
|
|
59
|
+
"displayName": "Slider",
|
|
60
|
+
"meta": {
|
|
61
|
+
"category": "forms",
|
|
62
|
+
"documentationUrl": "https://spectrum.adobe.com/page/slider/"
|
|
63
|
+
},
|
|
64
|
+
"anatomy": [
|
|
65
|
+
{ "name": "track" },
|
|
66
|
+
{
|
|
67
|
+
"name": "handle",
|
|
68
|
+
"lifecycle": {
|
|
69
|
+
"deprecated": "1.0.0-draft",
|
|
70
|
+
"deprecatedComment": "Renamed to thumb."
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/button.json",
|
|
77
|
+
"name": "button",
|
|
78
|
+
"displayName": "Button",
|
|
79
|
+
"meta": {
|
|
80
|
+
"category": "actions",
|
|
81
|
+
"documentationUrl": "https://spectrum.adobe.com/page/button/"
|
|
82
|
+
},
|
|
83
|
+
"states": [
|
|
84
|
+
{ "name": "hover" },
|
|
85
|
+
{
|
|
86
|
+
"name": "pressed",
|
|
87
|
+
"lifecycle": {
|
|
88
|
+
"deprecated": "1.0.0-draft",
|
|
89
|
+
"deprecatedComment": "Use active instead."
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"options": {
|
|
94
|
+
"variant": {
|
|
95
|
+
"type": "string",
|
|
96
|
+
"enum": ["primary", "secondary", "cta"],
|
|
97
|
+
"deprecatedEnumValues": {
|
|
98
|
+
"cta": {
|
|
99
|
+
"deprecated": "1.0.0-draft",
|
|
100
|
+
"deprecatedComment": "Use primary instead."
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
package/package.json
CHANGED
package/rules/rules.yaml
CHANGED
|
@@ -355,3 +355,18 @@ rules:
|
|
|
355
355
|
message: "Token '{token}' references deprecated component '{component}' (deprecated since {version}); update the reference or mark the token deprecated"
|
|
356
356
|
spec_ref: spec/component-format.md#lifecycle
|
|
357
357
|
introduced_in: "1.0.0-draft"
|
|
358
|
+
|
|
359
|
+
- id: SPEC-037
|
|
360
|
+
name: sub-entity-deprecation-cascade
|
|
361
|
+
severity: warning
|
|
362
|
+
category: reference-integrity
|
|
363
|
+
assert: >
|
|
364
|
+
Tokens SHOULD NOT reference a deprecated anatomy part, deprecated component state, or
|
|
365
|
+
deprecated option-enum value via their `name` object unless the token is itself deprecated.
|
|
366
|
+
Non-deprecated tokens referencing deprecated sub-entities are surfaced as warnings to
|
|
367
|
+
prompt authors to update the reference or mark the token deprecated.
|
|
368
|
+
Requires `lifecycle.deprecated` on anatomy parts and states, and `deprecatedEnumValues`
|
|
369
|
+
on option descriptors (introduced in this version of the schema).
|
|
370
|
+
message: "Token '{token}' references deprecated {kind} '{value}' on component '{component}' (deprecated since {version}); update the reference or mark the token deprecated"
|
|
371
|
+
spec_ref: spec/component-format.md#lifecycle
|
|
372
|
+
introduced_in: "1.0.0-draft"
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"items": { "$ref": "document-block.schema.json" },
|
|
36
36
|
"minItems": 1,
|
|
37
37
|
"description": "Typed prose blocks for this anatomy part. See spec/document-blocks.md (Phase 9)."
|
|
38
|
+
},
|
|
39
|
+
"lifecycle": {
|
|
40
|
+
"$ref": "component.schema.json#/$defs/lifecycle",
|
|
41
|
+
"description": "Version lifecycle metadata for this anatomy part. Set lifecycle.deprecated to signal that tokens referencing this part should migrate."
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
"additionalProperties": false
|
|
@@ -158,6 +158,14 @@
|
|
|
158
158
|
"type": "string",
|
|
159
159
|
"format": "uri-reference",
|
|
160
160
|
"description": "Reference to a shared type schema."
|
|
161
|
+
},
|
|
162
|
+
"deprecatedEnumValues": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"description": "Per-enum-value lifecycle metadata keyed by enum value string. Values absent from this map are not deprecated. Consumed by SPEC-037.",
|
|
165
|
+
"$comment": "Keys are not validated against sibling 'enum' — JSON Schema cannot cross-reference sibling values without unevaluatedProperties. Entries for values absent from 'enum' are silently ignored by validators. A future SPEC rule may close this gap.",
|
|
166
|
+
"additionalProperties": {
|
|
167
|
+
"$ref": "#/$defs/lifecycle"
|
|
168
|
+
}
|
|
161
169
|
}
|
|
162
170
|
},
|
|
163
171
|
"additionalProperties": true
|
|
@@ -209,6 +217,10 @@
|
|
|
209
217
|
"type": "array",
|
|
210
218
|
"items": { "$ref": "document-block.schema.json" },
|
|
211
219
|
"description": "Typed prose blocks for this anatomy part. See spec/document-blocks.md (Phase 9)."
|
|
220
|
+
},
|
|
221
|
+
"lifecycle": {
|
|
222
|
+
"$ref": "#/$defs/lifecycle",
|
|
223
|
+
"description": "Version lifecycle metadata for this anatomy part. Set lifecycle.deprecated to signal that tokens referencing this part should migrate."
|
|
212
224
|
}
|
|
213
225
|
},
|
|
214
226
|
"additionalProperties": false
|
|
@@ -255,6 +267,10 @@
|
|
|
255
267
|
"type": "boolean",
|
|
256
268
|
"default": false,
|
|
257
269
|
"description": "Whether this state prevents all user interaction. See spec/accessibility.md."
|
|
270
|
+
},
|
|
271
|
+
"lifecycle": {
|
|
272
|
+
"$ref": "#/$defs/lifecycle",
|
|
273
|
+
"description": "Version lifecycle metadata for this state. Set lifecycle.deprecated to signal that tokens referencing this state should migrate."
|
|
258
274
|
}
|
|
259
275
|
},
|
|
260
276
|
"additionalProperties": false
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"type": "boolean",
|
|
31
31
|
"default": false,
|
|
32
32
|
"description": "When true, this state composes on top of the winning non-layered state rather than competing with it. Use for focus rings, selection overlays, and similar compositing states."
|
|
33
|
+
},
|
|
34
|
+
"lifecycle": {
|
|
35
|
+
"$ref": "component.schema.json#/$defs/lifecycle",
|
|
36
|
+
"description": "Version lifecycle metadata for this state. Set lifecycle.deprecated to signal that tokens referencing this state should migrate."
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"additionalProperties": false
|
package/spec/anatomy-format.md
CHANGED
|
@@ -20,6 +20,7 @@ An anatomy part is a **JSON object** that appears as an element of a component d
|
|
|
20
20
|
| `description` | string | OPTIONAL | Plain-text description of the part's visual role and boundaries. |
|
|
21
21
|
| `required` | boolean | OPTIONAL | Whether this part is always rendered regardless of configuration. Default: `false`. |
|
|
22
22
|
| `contains` | array of strings | OPTIONAL | Informative list of child anatomy part names nested within this part (e.g. a `field` contains `["label", "help-text"]`). |
|
|
23
|
+
| `lifecycle` | object | OPTIONAL | Version lifecycle metadata for this anatomy part — see [lifecycle](#lifecycle). |
|
|
23
24
|
|
|
24
25
|
**NORMATIVE:** No properties beyond those listed above are permitted in an anatomy part object. Additional fields **MUST** cause a Layer 1 schema error.
|
|
25
26
|
|
|
@@ -51,6 +52,18 @@ When `required` is `true`, the anatomy part is unconditionally rendered (e.g. a
|
|
|
51
52
|
|
|
52
53
|
Each string in `contains` **MUST** match the pattern `^[a-z][a-z0-9-]*$`. References to anatomy part names not declared on the same component are permitted (they may refer to sub-component anatomy in layered designs) but validators **MAY** surface a warning for unresolved references.
|
|
53
54
|
|
|
55
|
+
### `lifecycle`
|
|
56
|
+
|
|
57
|
+
**OPTIONAL.** A version lifecycle object tracking the history of this anatomy part. Uses the same shape as the component-level `lifecycle` block (see [Component format — Lifecycle](component-format.md#lifecycle)).
|
|
58
|
+
|
|
59
|
+
| Field | Type | Description |
|
|
60
|
+
| ------------------- | ------ | ---------------------------------------------------------------------------------------------- |
|
|
61
|
+
| `deprecated` | string | Spec version when this anatomy part was deprecated. A truthy string signals deprecation. |
|
|
62
|
+
| `deprecatedComment` | string | Human-readable explanation of the deprecation and migration path (e.g. `"Renamed to thumb."`). |
|
|
63
|
+
| `replacedBy` | string | `name` of the replacement anatomy part. |
|
|
64
|
+
|
|
65
|
+
**ADVISORY:** When an anatomy part carries a `lifecycle.deprecated` value, non-deprecated tokens that reference this anatomy part via `name.anatomy` **SHOULD** be updated to remove or replace the reference. Rule SPEC-037 fires an advisory warning for such references to prompt migration.
|
|
66
|
+
|
|
54
67
|
```json
|
|
55
68
|
"anatomy": [
|
|
56
69
|
{
|
|
@@ -121,6 +134,7 @@ The following rules in the Layer 2 rule catalog (`rules/rules.yaml`) apply to an
|
|
|
121
134
|
| SPEC-024 | `anatomy-part-name-unique` | error | Anatomy part `name` values **MUST** be unique within a single component's `anatomy` array. |
|
|
122
135
|
| SPEC-025 | `anatomy-requires-component` | error | A token name object **MUST NOT** include an `anatomy` field unless a `component` field is also present. |
|
|
123
136
|
| SPEC-035 | `anatomy-part-name-registry-sync` | warning | A component anatomy part's `name` **SHOULD** appear in the canonical anatomy-terms registry (`anatomy-terms.json`). |
|
|
137
|
+
| SPEC-037 | `sub-entity-deprecation-cascade` | warning | A non-deprecated token **SHOULD NOT** reference a deprecated anatomy part via `name.anatomy`. Advisory warning prompts migration. |
|
|
124
138
|
|
|
125
139
|
## Full example
|
|
126
140
|
|
package/spec/component-format.md
CHANGED
|
@@ -88,13 +88,14 @@ The `options` block declares the component's API surface — the configurable pr
|
|
|
88
88
|
|
|
89
89
|
An option descriptor is a JSON object with the following fields:
|
|
90
90
|
|
|
91
|
-
| Field
|
|
92
|
-
|
|
|
93
|
-
| `type`
|
|
94
|
-
| `enum`
|
|
95
|
-
| `default`
|
|
96
|
-
| `description`
|
|
97
|
-
| `$ref`
|
|
91
|
+
| Field | Type | Required | Description |
|
|
92
|
+
| ---------------------- | --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
93
|
+
| `type` | string or array | OPTIONAL | JSON Schema primitive type(s): `"string"`, `"boolean"`, `"number"`, `"integer"`. |
|
|
94
|
+
| `enum` | array | OPTIONAL | Exhaustive list of permitted values. |
|
|
95
|
+
| `default` | any | OPTIONAL | Default value when the option is not specified. |
|
|
96
|
+
| `description` | string | OPTIONAL | Plain-text description of what the option controls. |
|
|
97
|
+
| `$ref` | URI string | OPTIONAL | Reference to a shared type schema (e.g. `workflow-icon.json`). |
|
|
98
|
+
| `deprecatedEnumValues` | object | OPTIONAL | Per-enum-value lifecycle metadata. Keys are enum value strings; values are lifecycle objects. Values absent from this map are not deprecated. |
|
|
98
99
|
|
|
99
100
|
**NORMATIVE:** Each key in `options` **MUST** be camelCase.
|
|
100
101
|
|
|
@@ -102,6 +103,23 @@ An option descriptor is a JSON object with the following fields:
|
|
|
102
103
|
|
|
103
104
|
**NORMATIVE:** When `enum` is present, token name-object `variant` field values referencing this component **MUST** be drawn from the declared `variant` option enum (rule SPEC-019). Other option enums are informative for tooling but do not currently drive SPEC rules.
|
|
104
105
|
|
|
106
|
+
**ADVISORY:** When a `deprecatedEnumValues` entry exists for a value that a non-deprecated token references via its `name` object field for that option, SPEC-037 fires an advisory warning. Keys in `deprecatedEnumValues` are not independently validated against `enum` — entries for values absent from `enum` are silently ignored by validators (a future rule may close this gap).
|
|
107
|
+
|
|
108
|
+
Example with a deprecated enum value:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
"variant": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"enum": ["primary", "secondary", "cta"],
|
|
114
|
+
"deprecatedEnumValues": {
|
|
115
|
+
"cta": {
|
|
116
|
+
"deprecated": "1.0.0-draft",
|
|
117
|
+
"deprecatedComment": "Use primary instead."
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
105
123
|
```json
|
|
106
124
|
"options": {
|
|
107
125
|
"variant": {
|
|
@@ -186,12 +204,13 @@ The `anatomy` block declares the component's named **visual parts** — the anat
|
|
|
186
204
|
|
|
187
205
|
Each anatomy part carries at minimum:
|
|
188
206
|
|
|
189
|
-
| Field | Type | Required | Description
|
|
190
|
-
| ------------- | ---------------- | -------- |
|
|
191
|
-
| `name` | string | REQUIRED | Anatomy part identifier (e.g. `icon`, `label`, `handle`).
|
|
192
|
-
| `description` | string | OPTIONAL | Plain-text description of the part.
|
|
193
|
-
| `required` | boolean | OPTIONAL | Whether this part is always present. Default: `false`.
|
|
194
|
-
| `contains` | array of strings | OPTIONAL | Informative: other anatomy part names nested within this part.
|
|
207
|
+
| Field | Type | Required | Description |
|
|
208
|
+
| ------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
209
|
+
| `name` | string | REQUIRED | Anatomy part identifier (e.g. `icon`, `label`, `handle`). |
|
|
210
|
+
| `description` | string | OPTIONAL | Plain-text description of the part. |
|
|
211
|
+
| `required` | boolean | OPTIONAL | Whether this part is always present. Default: `false`. |
|
|
212
|
+
| `contains` | array of strings | OPTIONAL | Informative: other anatomy part names nested within this part. |
|
|
213
|
+
| `lifecycle` | object | OPTIONAL | Version lifecycle metadata for this part. When `lifecycle.deprecated` is set, SPEC-037 fires on referencing tokens. |
|
|
195
214
|
|
|
196
215
|
See [`spec/anatomy-format.md`](anatomy-format.md) for constraints, cross-field validation, and the full anatomy part schema.
|
|
197
216
|
|
|
@@ -216,6 +235,7 @@ Each state carries at minimum:
|
|
|
216
235
|
| `trigger` | string | OPTIONAL | `"prop"` for persistent prop-driven states (e.g. `isDisabled`) or `"interaction"` for runtime interaction states (hover, focus, pressed). |
|
|
217
236
|
| `precedence` | integer | OPTIONAL | Resolution precedence; higher integer wins when multiple states are active. |
|
|
218
237
|
| `layered` | boolean | OPTIONAL | `true` for states that compose with others (e.g. focus ring over hover). Default: `false`. |
|
|
238
|
+
| `lifecycle` | object | OPTIONAL | Version lifecycle metadata for this state. When `lifecycle.deprecated` is set, SPEC-037 fires on referencing tokens. |
|
|
219
239
|
|
|
220
240
|
See [`spec/state-model.md`](state-model.md) for the full state resolution algorithm, trigger semantics, and precedence rules.
|
|
221
241
|
|
|
@@ -271,14 +291,16 @@ The `context` field is informative. It is used by `describe_component` (Phase 8
|
|
|
271
291
|
|
|
272
292
|
The following rules are added to the Layer 2 rule catalog (`rules/rules.yaml`) by this chapter. New component cross-reference rules start at SPEC-018 to avoid collision with existing token rules (SPEC-001–SPEC-017).
|
|
273
293
|
|
|
274
|
-
| Rule ID | Name
|
|
275
|
-
| -------- |
|
|
276
|
-
| SPEC-018 | `component-name-exists`
|
|
277
|
-
| SPEC-019 | `component-variant-valid`
|
|
278
|
-
| SPEC-020 | `component-anatomy-valid`
|
|
279
|
-
| SPEC-021 | `component-slot-vocabulary`
|
|
280
|
-
| SPEC-022 | `component-state-valid`
|
|
281
|
-
| SPEC-027 | `token-binding-token-exists`
|
|
294
|
+
| Rule ID | Name | Severity | Assert |
|
|
295
|
+
| -------- | -------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
296
|
+
| SPEC-018 | `component-name-exists` | error | Token `component` field value **MUST** match the `name` of a declared component in the dataset. |
|
|
297
|
+
| SPEC-019 | `component-variant-valid` | error | Token `variant` field value **MUST** match a value in the declared `variant` option enum for the referenced component (when that enum exists). |
|
|
298
|
+
| SPEC-020 | `component-anatomy-valid` | error | Token `anatomy` field value **MUST** match the `name` of a declared anatomy part on the referenced component. |
|
|
299
|
+
| SPEC-021 | `component-slot-vocabulary` | warning | Component `slots` entries with a `name` outside the canonical vocabulary **SHOULD** include a `description`. Custom slot names without descriptions are surfaced as warnings. |
|
|
300
|
+
| SPEC-022 | `component-state-valid` | error | Token `state` field value **MUST** match the `name` of a declared state on the referenced component (when state declarations are present). |
|
|
301
|
+
| SPEC-027 | `token-binding-token-exists` | error | Each `tokenBindings[].token` value **MUST** match the name of a declared token in the dataset (Phase 6.7). |
|
|
302
|
+
| SPEC-036 | `component-deprecation-cascade` | warning | A non-deprecated token **SHOULD NOT** reference a deprecated component via `name.component`. Advisory warning prompts updating the component reference or marking the token deprecated. |
|
|
303
|
+
| SPEC-037 | `sub-entity-deprecation-cascade` | warning | A non-deprecated token **SHOULD NOT** reference a deprecated anatomy part, state, or option-enum value via `name.*`. Advisory warning prompts migration. Requires `lifecycle` on anatomy/state or `deprecatedEnumValues` on option descriptor. |
|
|
282
304
|
|
|
283
305
|
## Full example
|
|
284
306
|
|
package/spec/state-model.md
CHANGED
|
@@ -34,6 +34,7 @@ A state declaration is a **JSON object** that appears as an element of a compone
|
|
|
34
34
|
| `trigger` | string | OPTIONAL | `"prop"` for persistent prop-driven states; `"interaction"` for runtime interaction states. See [Trigger semantics](#trigger-semantics). |
|
|
35
35
|
| `precedence` | integer | OPTIONAL | Resolution precedence; higher value wins when multiple non-layered states are active simultaneously. Defaults to `0` if omitted. |
|
|
36
36
|
| `layered` | boolean | OPTIONAL | When `true`, this state composes on top of the winning non-layered state rather than competing with it. Default: `false`. |
|
|
37
|
+
| `lifecycle` | object | OPTIONAL | Version lifecycle metadata for this state — see [lifecycle](#lifecycle). |
|
|
37
38
|
|
|
38
39
|
**NORMATIVE:** No properties beyond those listed above are permitted in a state declaration object. Additional fields **MUST** cause a Layer 1 schema error.
|
|
39
40
|
|
|
@@ -76,6 +77,18 @@ When `layered: true`, the state does not participate in the non-layered preceden
|
|
|
76
77
|
|
|
77
78
|
Typical use: focus ring states (`focus`, `focus-visible`) that must be visible regardless of whether the component is also in a `hover` or `selected` state.
|
|
78
79
|
|
|
80
|
+
### `lifecycle`
|
|
81
|
+
|
|
82
|
+
**OPTIONAL.** A version lifecycle object tracking the history of this state declaration. Uses the same shape as the component-level `lifecycle` block (see [Component format — Lifecycle](component-format.md#lifecycle)).
|
|
83
|
+
|
|
84
|
+
| Field | Type | Description |
|
|
85
|
+
| ------------------- | ------ | ------------------------------------------------------------------------------------------------ |
|
|
86
|
+
| `deprecated` | string | Spec version when this state was deprecated. A truthy string signals deprecation. |
|
|
87
|
+
| `deprecatedComment` | string | Human-readable explanation of the deprecation and migration path (e.g. `"Use active instead."`). |
|
|
88
|
+
| `replacedBy` | string | `name` of the replacement state. |
|
|
89
|
+
|
|
90
|
+
**ADVISORY:** When a state carries a `lifecycle.deprecated` value, non-deprecated tokens that reference this state via `name.state` **SHOULD** be updated to remove or replace the reference. Rule SPEC-037 fires an advisory warning for such references to prompt migration.
|
|
91
|
+
|
|
79
92
|
## Trigger semantics
|
|
80
93
|
|
|
81
94
|
### `prop` trigger
|
|
@@ -185,10 +198,11 @@ See [Token format — Name object](token-format.md#name-object) for the full nam
|
|
|
185
198
|
|
|
186
199
|
The following rules in the Layer 2 rule catalog (`rules/rules.yaml`) apply to state declarations. SPEC-022 was introduced in Phase 6.1 (component-format); SPEC-026 is introduced by this chapter.
|
|
187
200
|
|
|
188
|
-
| Rule ID | Name
|
|
189
|
-
| -------- |
|
|
190
|
-
| SPEC-022 | `component-state-valid`
|
|
191
|
-
| SPEC-026 | `state-custom-name-documented`
|
|
201
|
+
| Rule ID | Name | Severity | Assert |
|
|
202
|
+
| -------- | -------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
203
|
+
| SPEC-022 | `component-state-valid` | error | Token `state` field value **MUST** match the `name` of a declared state on the referenced component (when state declarations are present). |
|
|
204
|
+
| SPEC-026 | `state-custom-name-documented` | warning | State declarations with a `name` outside the canonical state vocabulary **SHOULD** include a `description` field documenting the state's semantics. |
|
|
205
|
+
| SPEC-037 | `sub-entity-deprecation-cascade` | warning | A non-deprecated token **SHOULD NOT** reference a deprecated state via `name.state`. Advisory warning prompts migration. |
|
|
192
206
|
|
|
193
207
|
## Full example
|
|
194
208
|
|