@adobe/design-data-spec 0.4.0 → 0.5.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.
Files changed (81) hide show
  1. package/components/accordion.json +431 -1
  2. package/components/action-bar.json +183 -1
  3. package/components/action-button.json +407 -1
  4. package/components/action-group.json +15 -1
  5. package/components/alert-banner.json +79 -1
  6. package/components/alert-dialog.json +107 -1
  7. package/components/avatar-group.json +115 -1
  8. package/components/avatar.json +131 -1
  9. package/components/badge.json +430 -1
  10. package/components/breadcrumbs.json +175 -1
  11. package/components/button-group.json +11 -1
  12. package/components/button.json +466 -8
  13. package/components/cards.json +483 -1
  14. package/components/checkbox-group.json +2 -1
  15. package/components/checkbox.json +243 -1
  16. package/components/close-button.json +123 -1
  17. package/components/coach-indicator.json +39 -1
  18. package/components/coach-mark.json +103 -1
  19. package/components/color-area.json +39 -1
  20. package/components/color-handle.json +51 -1
  21. package/components/color-loupe.json +55 -1
  22. package/components/color-slider.json +43 -1
  23. package/components/color-wheel.json +35 -1
  24. package/components/combo-box.json +387 -1
  25. package/components/contextual-help.json +83 -1
  26. package/components/date-picker.json +279 -1
  27. package/components/divider.json +47 -1
  28. package/components/drop-zone.json +167 -1
  29. package/components/field-label.json +147 -1
  30. package/components/help-text.json +147 -1
  31. package/components/illustrated-message.json +107 -1
  32. package/components/in-field-progress-circle.json +55 -1
  33. package/components/in-line-alert.json +155 -1
  34. package/components/link.json +91 -1
  35. package/components/list-view.json +263 -1
  36. package/components/menu.json +467 -1
  37. package/components/meter.json +115 -1
  38. package/components/number-field.json +399 -1
  39. package/components/opacity-checkerboard.json +19 -1
  40. package/components/picker.json +431 -1
  41. package/components/popover.json +51 -1
  42. package/components/progress-bar.json +115 -1
  43. package/components/progress-circle.json +55 -1
  44. package/components/radio-button.json +243 -1
  45. package/components/radio-group.json +2 -1
  46. package/components/rating.json +99 -1
  47. package/components/search-field.json +235 -1
  48. package/components/segmented-control.json +135 -1
  49. package/components/select-box.json +187 -1
  50. package/components/side-navigation.json +223 -1
  51. package/components/slider.json +279 -1
  52. package/components/standard-dialog.json +99 -1
  53. package/components/status-light.json +219 -1
  54. package/components/steplist.json +215 -1
  55. package/components/swatch-group.json +15 -1
  56. package/components/swatch.json +136 -2
  57. package/components/switch.json +251 -1
  58. package/components/table.json +271 -1
  59. package/components/tabs.json +151 -1
  60. package/components/tag-field.json +151 -1
  61. package/components/tag-group.json +19 -1
  62. package/components/tag.json +323 -1
  63. package/components/takeover-dialog.json +35 -1
  64. package/components/text-area.json +383 -1
  65. package/components/text-field.json +411 -1
  66. package/components/thumbnail.json +83 -1
  67. package/components/title.json +39 -0
  68. package/components/toast.json +99 -1
  69. package/components/tooltip.json +87 -1
  70. package/components/tree-view.json +279 -1
  71. package/conformance/invalid/SPEC-027/dataset.json +25 -0
  72. package/conformance/invalid/SPEC-027/expected-errors.json +10 -0
  73. package/conformance/valid/token-bindings.json +27 -0
  74. package/package.json +1 -1
  75. package/rules/rules.yaml +9 -0
  76. package/schemas/component.schema.json +22 -0
  77. package/schemas/token.schema.json +27 -0
  78. package/spec/agent-surface.md +39 -9
  79. package/spec/component-format.md +41 -16
  80. package/spec/token-format.md +18 -0
  81. package/src/validate.js +27 -3
@@ -29,15 +29,16 @@ A component declaration **MUST** contain:
29
29
 
30
30
  ### Optional fields
31
31
 
32
- | Field | Type | Description |
33
- | ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
34
- | `specVersion` | string | Declares which spec version this document targets. Currently `"1.0.0-draft"`; future stable releases will accept their own version string. |
35
- | `description` | string | Plain-text description of the component's purpose. |
36
- | `options` | object | Component API options — see [Options](#options). |
37
- | `slots` | array | Named content injection points — see [Slots](#slots). |
38
- | `anatomy` | array | Named anatomy parts — see [Anatomy (stub)](#anatomy-stub). |
39
- | `states` | array | Per-component state declarations — see [States (stub)](#states-stub). |
40
- | `lifecycle` | object | Version lifecycle metadata — see [Lifecycle](#lifecycle). |
32
+ | Field | Type | Description |
33
+ | --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
34
+ | `specVersion` | string | Declares which spec version this document targets. Currently `"1.0.0-draft"`; future stable releases will accept their own version string. |
35
+ | `description` | string | Plain-text description of the component's purpose. |
36
+ | `options` | object | Component API options — see [Options](#options). |
37
+ | `slots` | array | Named content injection points — see [Slots](#slots). |
38
+ | `anatomy` | array | Named anatomy parts — see [Anatomy (stub)](#anatomy-stub). |
39
+ | `states` | array | Per-component state declarations — see [States (stub)](#states-stub). |
40
+ | `lifecycle` | object | Version lifecycle metadata — see [Lifecycle](#lifecycle). |
41
+ | `tokenBindings` | array | Tokens this component uses — see [Token bindings](#token-bindings) (Phase 6.7). |
41
42
 
42
43
  **NORMATIVE:** No properties beyond those listed above are permitted at the top level of a component declaration. Additional fields **MUST** cause a Layer 1 schema error.
43
44
 
@@ -241,17 +242,41 @@ The `lifecycle` block tracks a component declaration's version history. It mirro
241
242
  }
242
243
  ```
243
244
 
245
+ ## Token bindings
246
+
247
+ The optional `tokenBindings` array declares which tokens a component uses, including foundation and structure tokens that do not carry the component name in their name-object. This is the *component-declares-usage* direction; the *token-declares-scope* direction is expressed via name-object `component`/`anatomy`/`state` fields and validated by SPEC-018–022.
248
+
249
+ ```json
250
+ "tokenBindings": [
251
+ { "token": "component-height-100", "context": "Minimum height" },
252
+ { "token": "corner-radius-full", "context": "Rounding" },
253
+ { "token": "button-background-color-accent", "context": "Fill background" }
254
+ ]
255
+ ```
256
+
257
+ Each entry contains:
258
+
259
+ | Field | Required | Type | Description |
260
+ | --------- | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
261
+ | `token` | yes | string | Token name. **MUST** resolve to a declared token in the dataset when the dataset is present (rule SPEC-027). May reference structure/foundation tokens. |
262
+ | `context` | no | string | Human-readable label for how this token is used (maps to the Figma Token Group label in the S2 Token Specs Figma file). |
263
+
264
+ **NORMATIVE:** When the dataset includes token declarations, each `tokenBindings[].token` value **MUST** match the name of a declared token (rule SPEC-027). A missing token reference is a validation error.
265
+
266
+ The `context` field is informative. It is used by `describe_component` (Phase 8 agent surface) to present token usage in grouped, human-readable form.
267
+
244
268
  ## SPEC rules
245
269
 
246
270
  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).
247
271
 
248
- | Rule ID | Name | Severity | Assert |
249
- | -------- | --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
250
- | SPEC-018 | `component-name-exists` | error | Token `component` field value **MUST** match the `name` of a declared component in the dataset. |
251
- | 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). |
252
- | SPEC-020 | `component-anatomy-valid` | error | Token `anatomy` field value **MUST** match the `name` of a declared anatomy part on the referenced component. |
253
- | 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. |
254
- | 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). |
272
+ | Rule ID | Name | Severity | Assert |
273
+ | -------- | ---------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
274
+ | SPEC-018 | `component-name-exists` | error | Token `component` field value **MUST** match the `name` of a declared component in the dataset. |
275
+ | 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). |
276
+ | SPEC-020 | `component-anatomy-valid` | error | Token `anatomy` field value **MUST** match the `name` of a declared anatomy part on the referenced component. |
277
+ | 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. |
278
+ | 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). |
279
+ | 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). |
255
280
 
256
281
  ## Full example
257
282
 
@@ -218,6 +218,24 @@ Within a composite value, a string sub-value **MAY** be an **inline alias**: a r
218
218
 
219
219
  **NORMATIVE:** Inline aliases within composite values are subject to alias resolution rules. Validators **MUST** resolve inline aliases and report errors for missing targets (SPEC-014), type mismatches (SPEC-015), and circular references (SPEC-003, extended).
220
220
 
221
+ ## Component bindings
222
+
223
+ The optional `componentBindings` array on a token is the **reverse index** of `tokenBindings` on a component declaration (Phase 6.7). It declares which components reference this token in their `tokenBindings` list.
224
+
225
+ ```json
226
+ "componentBindings": [
227
+ { "component": "button", "context": "Minimum height" },
228
+ { "component": "checkbox", "context": "Height" }
229
+ ]
230
+ ```
231
+
232
+ | Field | Required | Type | Description |
233
+ | ----------- | -------- | ------ | -------------------------------------------------------------------- |
234
+ | `component` | yes | string | Component name (kebab-case). MUST match a declared component `name`. |
235
+ | `context` | no | string | Human-readable label for how this token is used in the component. |
236
+
237
+ `componentBindings` is **informative and optional**. It is fully derivable from the `tokenBindings` arrays on component declarations and does not need to be hand-maintained. Tooling that generates component files may populate `componentBindings` as a convenience for consumers that query token files directly.
238
+
221
239
  ## Relationship to legacy Spectrum tokens
222
240
 
223
241
  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 [#743](https://github.com/adobe/spectrum-design-data/issues/743).
package/src/validate.js CHANGED
@@ -13,9 +13,9 @@ governing permissions and limitations under the License.
13
13
  /**
14
14
  * Layer 2 cross-reference validator for design-data-spec.
15
15
  *
16
- * Implements SPEC-018 through SPEC-024: semantic rules that validate token
17
- * name-object fields against component declarations, and validate component
18
- * declarations internally.
16
+ * Implements SPEC-018 through SPEC-027: semantic rules that validate token
17
+ * name-object fields against component declarations, validate component
18
+ * declarations internally, and validate tokenBindings references.
19
19
  *
20
20
  * @see spec/component-format.md#spec-rules
21
21
  * @see spec/anatomy-format.md#spec-rules
@@ -162,5 +162,29 @@ export function validateDataset(dataset) {
162
162
  }
163
163
  }
164
164
 
165
+ // --- Token binding rules ---
166
+
167
+ // SPEC-027: each tokenBindings[].token must resolve to a known token name.
168
+ // String-named tokens are matched directly. Name-object tokens are skipped
169
+ // here because tokenBindings always reference tokens by their string name.
170
+ const tokenNameSet = new Set(
171
+ tokens
172
+ .map((t) => (typeof t.name === "string" ? t.name : null))
173
+ .filter(Boolean),
174
+ );
175
+
176
+ for (const component of components) {
177
+ for (const binding of component.tokenBindings ?? []) {
178
+ if (!tokenNameSet.has(binding.token)) {
179
+ diagnostics.push({
180
+ ruleId: "SPEC-027",
181
+ severity: "error",
182
+ message: `Component '${component.name}' tokenBindings references unknown token '${binding.token}'`,
183
+ componentName: component.name,
184
+ });
185
+ }
186
+ }
187
+ }
188
+
165
189
  return diagnostics;
166
190
  }