@adobe/design-data-spec 2.7.0 → 2.8.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.
@@ -0,0 +1,21 @@
1
+ {
2
+ "tokens": [],
3
+ "components": [
4
+ {
5
+ "$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/menu.json",
6
+ "name": "menu",
7
+ "displayName": "Menu",
8
+ "meta": {
9
+ "category": "collections",
10
+ "documentationUrl": "https://spectrum.adobe.com/page/menu/"
11
+ },
12
+ "anatomy": [
13
+ {
14
+ "name": "menu-item",
15
+ "description": "A single row within the menu.",
16
+ "contains": ["item-checkbox"]
17
+ }
18
+ ]
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "layer": 2,
3
+ "errors": [
4
+ {
5
+ "rule_id": "SPEC-048",
6
+ "severity": "warning",
7
+ "message_pattern": ".*menu-item.*item-checkbox.*"
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "tokens": [],
3
+ "components": [
4
+ {
5
+ "$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/menu.json",
6
+ "name": "menu",
7
+ "displayName": "Menu",
8
+ "meta": {
9
+ "category": "collections",
10
+ "documentationUrl": "https://spectrum.adobe.com/page/menu/"
11
+ },
12
+ "anatomy": [
13
+ {
14
+ "name": "menu-item",
15
+ "description": "A single row within the menu.",
16
+ "contains": ["item-icon", "item-label"]
17
+ },
18
+ { "name": "item-icon", "description": "Leading icon of a menu item." },
19
+ { "name": "item-label", "description": "Label text of a menu item." }
20
+ ]
21
+ }
22
+ ]
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/design-data-spec",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Design Data Specification — prose, JSON Schemas, rule catalog, and conformance fixtures for the design data format",
5
5
  "type": "module",
6
6
  "repository": {
package/rules/rules.yaml CHANGED
@@ -544,3 +544,19 @@ rules:
544
544
  message: "Token '{token}' has space-between endpoint '{endpoint}' that is not a known position, anatomy term, or declared anatomy part on component '{component}'"
545
545
  spec_ref: spec/token-format.md#space-between-endpoints
546
546
  introduced_in: "1.0.0-draft"
547
+
548
+ - id: SPEC-048
549
+ name: anatomy-contains-resolves
550
+ severity: warning
551
+ layer: 2
552
+ category: completeness
553
+ assert: >
554
+ Each string in an anatomy part's `contains` array SHOULD match the `name` of
555
+ another anatomy part declared on the same component. Unresolved references are
556
+ advisory rather than an error: `contains` may legitimately point at sub-component
557
+ anatomy in layered designs (anatomy-format.md#contains), so this rule only warns
558
+ when a `contains` entry cannot be resolved against the same component's declared
559
+ parts.
560
+ message: "Anatomy part '{part}' on component '{component}' contains '{child}', which is not a declared anatomy part on this component"
561
+ spec_ref: spec/anatomy-format.md#contains
562
+ introduced_in: "1.0.0-draft"
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/anatomy-part.schema.json",
4
4
  "title": "Anatomy part declaration",
5
- "description": "Layer 1 structural schema for a single anatomy part object within a component declaration. Semantic rules (component-anatomy-valid, anatomy-custom-part-documented, anatomy-part-name-unique, anatomy-requires-component) are Layer 2.",
5
+ "description": "Layer 1 structural schema for a single anatomy part object within a component declaration. Semantic rules (component-anatomy-valid, anatomy-custom-part-documented, anatomy-part-name-unique, anatomy-requires-component, anatomy-contains-resolves) are Layer 2.",
6
6
  "type": "object",
7
7
  "required": ["name"],
8
8
  "properties": {
@@ -28,7 +28,7 @@
28
28
  "pattern": "^[a-z][a-z0-9-]*$"
29
29
  },
30
30
  "uniqueItems": true,
31
- "description": "Informative list of child anatomy part names nested within this part. Does not carry enforcement semantics."
31
+ "description": "List of child anatomy part names nested within this part. SHOULD reference a `name` declared elsewhere in the same component's anatomy array; unresolved references are permitted (they may point at sub-component anatomy in layered designs) but rule anatomy-contains-resolves fires an advisory warning."
32
32
  },
33
33
  "documentBlocks": {
34
34
  "type": "array",
@@ -225,7 +225,7 @@
225
225
  "contains": {
226
226
  "type": "array",
227
227
  "items": { "type": "string" },
228
- "description": "Informative: anatomy part names nested within this part."
228
+ "description": "Anatomy part names nested within this part. SHOULD reference a `name` declared elsewhere in this component's anatomy array (see anatomy-contains-resolves)."
229
229
  },
230
230
  "documentBlocks": {
231
231
  "type": "array",
@@ -51,6 +51,10 @@
51
51
  "type": "string",
52
52
  "description": "Semantic: interactive or semantic state (e.g. hover, focus, disabled)."
53
53
  },
54
+ "qualifier": {
55
+ "type": "string",
56
+ "description": "Semantic: behavioral or layout modifier that narrows a property/anatomy without being a state, variant, or position (e.g. stacked, multiline, precision, collapsed, expanded, drag, highlight)."
57
+ },
54
58
  "orientation": {
55
59
  "type": "string",
56
60
  "description": "Semantic: direction or order (e.g. vertical, horizontal)."
@@ -71,6 +75,10 @@
71
75
  "type": "string",
72
76
  "description": "Semantic: overall component shape (e.g. uniform)."
73
77
  },
78
+ "role": {
79
+ "type": "string",
80
+ "description": "Semantic: an object's role within a nesting relationship (e.g. container, control), distinct from `size`."
81
+ },
74
82
  "from": {
75
83
  "type": "string",
76
84
  "description": "Semantic: starting endpoint of a space-between measurement (e.g. top, edge, text). Paired with `to`; used with property `space-between`."
@@ -90,6 +98,11 @@
90
98
  "contrast": {
91
99
  "type": "string",
92
100
  "description": "Mode set: contrast level (e.g. regular, high)."
101
+ },
102
+ "legacyKey": {
103
+ "type": "string",
104
+ "minLength": 1,
105
+ "description": "Escape hatch: pins the exact flat key written to legacy output (packages/tokens/src), overriding reconstruction from the rest of this name object. Use when correcting or extending a token's decomposition would otherwise change its published legacy key."
93
106
  }
94
107
  },
95
108
  "additionalProperties": {
@@ -46,11 +46,13 @@ When `required` is `true`, the anatomy part is unconditionally rendered (e.g. a
46
46
 
47
47
  ### `contains`
48
48
 
49
- **OPTIONAL.** An informative list of child anatomy part `name` values that are visually or structurally nested within this part. This field is for documentation and tooling assistance; it does not carry enforcement semantics.
49
+ **OPTIONAL.** A list of child anatomy part `name` values that are visually or structurally nested within this part.
50
50
 
51
- **RECOMMENDED:** When a part logically encloses other declared anatomy parts, authors **SHOULD** use `contains` to make the nesting explicit.
51
+ **RECOMMENDED:** When a part logically encloses other declared anatomy parts, authors **SHOULD** use `contains` to make the nesting explicit, rather than declaring the children only as flat, unrelated parts.
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
+ 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 a reference that cannot be resolved against the same component's declared parts triggers an advisory warning (rule SPEC-048, `anatomy-contains-resolves`) — it is not an error.
54
+
55
+ **Authoring convention — flat vs. nested:** declare a part as a flat leaf when it has no meaningful internal sub-structure of its own (e.g. `label`, `icon`). Declare a part with `contains` when it is a composite that visually groups other declared parts (e.g. a `menu-item` row containing an `icon` and a `label`, or a `list-item` row containing a `checkbox`, `thumbnail`, and `label`). Prefer the canonical vocabulary (below) for children where the semantics match, falling back to a documented custom name (SPEC-023) otherwise.
54
56
 
55
57
  ### `lifecycle`
56
58
 
@@ -135,6 +137,7 @@ The following rules in the Layer 2 rule catalog (`rules/rules.yaml`) apply to an
135
137
  | SPEC-025 | `anatomy-requires-component` | error | A token name object **MUST NOT** include an `anatomy` field unless a `component` field is also present. |
136
138
  | 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
139
  | 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. |
140
+ | SPEC-048 | `anatomy-contains-resolves` | warning | An anatomy part's `contains` entries **SHOULD** match the `name` of another part declared on the same component. Advisory warning for unresolved entries. |
138
141
 
139
142
  ## Full example
140
143
 
package/spec/taxonomy.md CHANGED
@@ -73,6 +73,7 @@ The following concept categories are defined in Spectrum's foundation field cata
73
73
  | Size | `size` | When/Why? | Relative terms used to create relationships and patterns of usage across multiple tokens and token types. |
74
74
  | Density | `density` | When/Why? | Options that create more or less space within or around the parts of a component. |
75
75
  | Shape | `shape` | When/Why? | Relative to the overall shape of a component (e.g. "uniform" creates a 1:1 padding ratio between horizontal and vertical padding). |
76
+ | Role | `role` | When/Why? | An object's role within a nesting relationship (e.g. `container`, `control`), distinct from `size` — e.g. corner-radius tokens where a container and its nested control each need an independently-scaled rounding step. |
76
77
 
77
78
  Additional categories for variant and state are inherited from the existing name object:
78
79
 
@@ -70,6 +70,7 @@ The table below lists all semantic fields. Fields marked with a scope are domain
70
70
  | `size` | OPTIONAL | Size | Relative t-shirt sizing for relationships across tokens (e.g. `small`, `medium`, `large`). |
71
71
  | `density` | OPTIONAL | Density | Space within or around component parts (e.g. `spacious`, `compact`). |
72
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`. |
73
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. |
74
75
  | `from` | OPTIONAL | — | Starting endpoint of a `space-between` measurement (e.g. `top`, `edge`, `text`). See [Space-between endpoints](#space-between-endpoints). |
75
76
  | `to` | OPTIONAL | — | Ending endpoint of a `space-between` measurement (e.g. `text`, `visual`, `control`). See [Space-between endpoints](#space-between-endpoints). |