Skip to content

feat(anatomy): anatomy standard, presentIn, SPEC-073 to 075 and flowed-box painting (4/6) - #1580

Merged
GarthDB merged 19 commits into
next/visual-recipesfrom
feat/anatomy-s4
Nov 1, 2026
Merged

GarthDB merged 19 commits into
next/visual-recipesfrom
feat/anatomy-s4

Conversation

@GarthDB

@GarthDB GarthDB commented Oct 31, 2026

Copy link
Copy Markdown
Member

Squash merge is fine; the next slice is rebased onto the result.

Description

Slice 4 of 6 from #1569, into next/visual-recipes, now rebased onto the merged 3b (#1579). It defines what an anatomy part is and enforces it, then reviews the first five components against that definition.

  • Spec: anatomy-format.md defines parts, naming, nesting, required parts, non-anatomy, and a review checklist. New optional presentIn on a part (states it is present in; not allowed on a required part). New optional anatomyReview (draft or reviewed) on a component.
  • Rules: SPEC-073 (info: relationships but no anatomy, or draft anatomy), SPEC-074 (error: presentIn states must be declared on the component), SPEC-075 (error: a recipe's visibleWhen.states must agree with presentIn). Conformance fixtures for SPEC-059 to SPEC-063, SPEC-066 to SPEC-071 and SPEC-073 to SPEC-075.
  • Tooling: design-data anatomy-suggest proposes candidate parts for a component. State-name normalization is shared as state_ids. The site shows state-only parts such as the focus indicator.
  • Data: button, action-button, badge, checkbox and switch anatomy reviewed. Button label is optional. The focus indicator is state-only.
  • Painting: a box placed directly in a row paints fill, stroke and strokeWidth itself, so checkbox and switch drop the render-only control part. Relationships move to box / track. Rendered geometry, colors and press scale are unchanged (measured below).

Changesets: anatomy-definition-and-review (button, action-button, badge review and the standard) and flowed-box-paints (flowed-box painting; checkbox and switch review).

Related Issue

Part of #1569. Tracked in bead spectrum-design-data-p6ga.9.

Motivation and Context

Anatomy was loosely defined, so each component's parts were ad hoc and recipes could disagree with them. A written standard plus rules makes the data checkable. The flowed-box change removes a part that existed only for rendering, which the new standard calls out as not anatomy.

How Has This Been Tested?

Run in a clean worktree on the rebased branch (macOS):

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings
  • moon run sdk:test sdk-wasm:test design-data:validate design-data:validate-dataset tokens:verifyLegacyOutput --force: 1691 Rust tests passed, 2 skipped; the working tree was clean afterward, so no snapshot, golden or legacy output drifted beyond what the commits below commit on purpose
  • node tools/changeset-linter/src/cli.js check --fail-on-warnings
  • node .github/scripts/check-ci-coverage.mjs, pnpm ai:check
  • Root pnpm-lock.yaml diff is empty

Rendered output before and after (checkbox, switch). I rendered both components on the integration branch (bf40d547, old data) and on this branch (new data) over the same full sweep: every option set the recipe uses (booleans and declared values; combinations an error constraint excludes are skipped) across every size, interaction state, color scheme (light, dark, wireframe) and scale (desktop, mobile). Each pair of scenes was compared as SVG text, with the old data-part control mapped to box (checkbox) or track (switch):

Component Option sets compared Scenes compared Sets differing Scenes differing
checkbox 32 3,072 0 0
switch 16 1,536 0 0
Total 48 4,608 0 0

How the mapping works. The old SVG has an unpainted control rect (fill="none") with the same x, y, width and height as the part that paints the box. The comparison drops that rect, after checking that its geometry equals the new box/track rect and that it was unpainted. Then the SVGs must be identical, with data-tokens stripped. For data-tokens, the new box/track list must equal the union of the old control and box/track lists (the order differs). The press info (part, nested, scale, center) must match with control mapped to box (checkbox: nested loses box). Diagnostics must match. Nothing else differed. Switch press was already on handle and is unchanged.

The committed goldens and recipe-snapshots.json change only because of that removal of control and the data-tokens order. The scratch test that produced the numbers is not committed. sdk/core/tests/recipe_snapshots.rs and the visual goldens guard this output from now on.

Screenshots (if appropriate):

None. Checkbox and switch render the same geometry and colors.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Review guide (reading order)

  1. packages/design-data-spec/spec/anatomy-format.md, schemas/anatomy-part.schema.json, rules/rules.yaml: the standard and rule entries.
  2. sdk/core/src/validate/rules/spec073.rs, spec074.rs, spec075.rs, plus schema.rs, lib.rs: the rules.
  3. Fixtures (mostly mechanical; skim), one directory each under packages/design-data-spec/conformance/invalid/: SPEC-059, SPEC-060, SPEC-061, SPEC-062, SPEC-063, SPEC-066, SPEC-067, SPEC-068, SPEC-069, SPEC-070, SPEC-071, SPEC-073, SPEC-074, SPEC-075.
  4. sdk/core/src/anatomy_suggest.rs, sdk/cli/src/main.rs: the suggester (largest new file, self-contained).
  5. packages/design-data/components/{button,action-button,badge,checkbox,switch}.json: the per-component reviews (one commit per component).
  6. sdk/core/src/visual.rs, sdk/plugins/site/assets/visual-runtime.js, index.html, then visuals/ and relationships/ for checkbox and switch: flowed-box painting.
  7. Snapshots and goldens last.
  8. .changeset/anatomy-definition-and-review.md, .changeset/flowed-box-paints.md.

test added 19 commits October 31, 2026 17:47
- label: required -> optional (hidden by isLabelHidden and while pending)
- focus-indicator: mark state-only (states: [focus])
- progress: description generalised; kept, button styles it and isPending drives it
- add anatomyReview: reviewed
- focus-indicator: mark state-only (states: [keyboard-focus])
- progress: description generalised; kept
- hold-icon: kept (registry term, own style)
- add anatomyReview: reviewed
- no part changes; icon and label already optional, not focusable
- add anatomyReview: reviewed
- focus-indicator: mark state-only; no longer nested in control
- box: required (always drawn)
- control: kept but flagged; it is a render-only wrapper (flowed boxes cannot paint)
- anatomyReview stays draft until control can be removed
- focus-indicator: mark state-only; no longer nested in control
- track: required (always drawn)
- control: kept but flagged; it is a render-only wrapper (flowed boxes cannot paint)
- anatomyReview stays draft until control can be removed
…natomy view

The anatomy callouts filtered out every ring node, so the focus indicator never
appeared even with the focus state selected. Rings now get a callout while
their state is active, placed below on the ring's bottom edge so the other
labels keep their alternation. Fit and compact/large labels are unchanged.
…anatomy

One info diagnostic lists components that have relationships but no anatomy and
components whose anatomy is still draft. Adds the rule catalog entry, spec table
row, conformance fixture and changeset.
… part

A box placed directly in a row only read width, height and corner radius, so a
painted box had to nest inside a sized wrapper. The renderer and the JS runtime
now read fill, stroke and strokeWidth on a flowed box.

- checkbox: control removed; box carries the size and holds the checkmark and dash
- switch: control removed; track carries the size and holds the handle
- relationships that named control now name box or track
- anatomyReview is reviewed for both
- snapshots and golden SVGs regenerated; 1536 old and new scene renders match in
  geometry, paint, token traces and press scale, minus the empty control node
… review

design-data anatomy-suggest [COMPONENT...] [--format markdown|json] reads
relationship scope.part and context text, token name.anatomy and component
options, and prints candidate parts with their evidence. It never writes
component files and every result is a draft.

Candidates are checked against the anatomy definition:
- registry terms are marked, custom names are flagged with the nearest term
- platform words, layout helpers, measurements, variants and compound phrases
  are listed as not proposed, with the reason
- spacing-only evidence, repeated component names and plurals are flagged
- the focus indicator gets the component's declared focus state for `states`
…required parts

presentIn says a part is present only in the listed states (drawn when any is
active). State-dependent styling is not presence and stays off the part.

- anatomy-format.md: definition of presentIn, checklist item 7
- anatomy-part and component schemas: rename, and a Layer 1 condition that
  rejects required: true together with presentIn
- button, action-button, checkbox, switch: focus-indicator uses presentIn
- anatomy-suggest: candidates carry presentIn
- schema tests cover valid, required-with-presentIn and the old field name
name_states now delegates one state name to state_ids, so validation rules can
normalize a state name the same way the renderer does. No behavior change.
A part that lists a state the component does not declare is a dangling
reference, the anatomy version of SPEC-054. States are compared after the
engine's normalization, so focus, key-focus and keyboard-focus are one state.
A part with presentIn on a component that declares no states is also reported.

Warning while anatomy is unreviewed; it should become an error after the
review pass. Adds the rules.yaml entry, spec table row, conformance fixture,
unit tests and a changeset update.
The fixture harness read relationships but not visual recipes, so rules that
check a recipe against component data could not have a conformance fixture.
A dataset.json may now carry a visuals array of recipes.
…ee on states

A recipe part's visibleWhen.states should match the presentIn of the anatomy
part of the same name, so the focus indicator's visibility cannot drift between
the two. States are compared after normalization.

visibleWhen.states means all listed states and presentIn means any, so a
difference is a warning only when neither side lists more than one state;
otherwise it is reported at info level. Adds the rules.yaml entry, spec rows,
a conformance fixture that uses the new visuals support, unit tests and a
changeset update.
SPEC-060 to 063 and SPEC-066 to 071 only had unit tests. Each rule now has an
invalid fixture with a dataset (recipes in the visuals key) and the expected
diagnostic, matched on severity and message. SPEC-070 expects both of its
diagnostics. The README table lists the new fixtures, including SPEC-072 to
075, which were missing from it.
An alias pinned to colorScheme dark that resolves to a light token now has an
invalid fixture and a README row.
The five components with anatomy are reviewed and the dataset is clean, so an
undeclared presentIn state (SPEC-074) and a recipe whose visibleWhen.states
disagrees with presentIn (SPEC-075) are now errors. SPEC-075 stays at info
level when either side lists more than one state, because visibleWhen.states
means all and presentIn means any.

Updates the rule catalog, spec wording and tables, fixtures, unit tests and
the changeset.
@changeset-bot

changeset-bot Bot commented Oct 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd8d71a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@adobe/design-data-spec Minor
@adobe/spectrum-design-data Patch
@adobe/design-data-wasm Patch
@adobe/spectrum-component-api-schemas Patch
@adobe/design-data Patch
@adobe/design-system-registry Patch
@adobe/design-data-agent-mcp Patch
@adobe/design-data-mcp Patch
markdown-generator Patch
@adobe/token-corpus-migrate Patch
@adobe/token-naming-audit Patch
s2-tokens-viewer Patch
@adobe/spectrum-design-data-mcp Patch
component-options-editor Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Run report for cd8d71a0

Total time: 8m 56s | Comparison time: 23m 5s | Estimated savings: 14m 9s (61.3% faster)

Action Time Status Info
⬛️ SetupProto(0.57.4) 0ms Skipped
🟩 SyncWorkspace 11ms Passed
🟩 SyncProject(sdk) 6.6ms Passed
🟩 SyncProject(design-data-spec) 6.6ms Passed
🟩 SyncProject(sdk-wasm) 1.1ms Passed
🟩 SyncProject(design-data) 1.5ms Passed
🟩 SyncProject(design-data-glue) 1.3ms Passed
🟩 SyncProject(design-data-mcp) 1.3ms Passed
⬛️ SetupToolchain(node:20.17.0) 594.3ms Skipped
⬛️ SetupToolchain(rust:1.88.0) 815.6ms Skipped
🟩 SetupEnvironment(rust, sdk) 115.3ms Passed
⬛️ InstallDependencies(rust, sdk) 2.6ms Skipped
⬛️ SetupToolchain(pnpm:10.17.1) 793.2ms Skipped
⬛️ SetupToolchain(javascript) 0ms Skipped
🟩 SetupEnvironment(javascript) 0.9ms Passed
⬛️ InstallDependencies(javascript) 0.4ms Skipped
⬛️ SetupEnvironment(javascript, sdk) 1.4ms Skipped
🟩 RunTask(design-data:validate-registry) 393.2ms Passed
🟩 RunTask(design-data:validate-visuals) 292.3ms Passed
🟩 RunTask(sdk:fmt-check) 1.3s Passed
And 16 more...
Expanded report
Action Time Status Info
🟩 InstallDependencies(javascript, sdk) 5.8s Passed
🟩 RunTask(sdk:codegen-check) 218.7ms Passed
🟩 RunTask(sdk:lint) 1m 4s Passed
🟩 RunTask(sdk:test-doc) 2m 10s Passed SLOW
🟩 RunTask(sdk:build) 2m 28s Passed SLOW
🟩 RunTask(design-data:legacy-output) 1.1s Passed
🟩 RunTask(design-data:validate-dataset) 28.8s Passed
🟩 RunTask(design-data:validate) 46.2s Passed
🟩 RunTask(sdk-wasm:cache-build) 3m 19s Passed SLOW
🟩 RunTask(sdk:test) 6m 49s Passed SLOW
🟩 RunTask(sdk-wasm:site-data) 5m 3s Passed SLOW
🟩 RunTask(sdk-wasm:build) 4m 9s Passed SLOW
🟩 RunTask(design-data-mcp:stage) 1.8s Passed
🟩 RunTask(sdk-wasm:test) 15.6s Passed
🟩 RunTask(sdk-wasm:ci) 15.7ms Passed
🟩 RunTask(design-data-mcp-eval:test) 19.1s Passed
Changed files
.changeset/anatomy-definition-and-review.md
.changeset/flowed-box-paints.md
packages/design-data-spec/conformance/README.md
packages/design-data-spec/conformance/invalid/SPEC-059/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-059/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-060/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-060/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-061/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-061/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-062/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-062/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-063/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-063/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-066/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-066/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-067/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-067/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-068/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-068/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-069/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-069/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-070/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-070/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-071/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-071/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-073/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-073/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-074/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-074/expected-errors.json
packages/design-data-spec/conformance/invalid/SPEC-075/dataset.json
packages/design-data-spec/conformance/invalid/SPEC-075/expected-errors.json
packages/design-data-spec/rules/rules.yaml
packages/design-data-spec/schemas/anatomy-part.schema.json
packages/design-data-spec/schemas/component.schema.json
packages/design-data-spec/spec/anatomy-format.md
packages/design-data-spec/spec/component-visuals.md
packages/design-data/components/action-button.json
packages/design-data/components/badge.json
packages/design-data/components/button.json
packages/design-data/components/checkbox.json
packages/design-data/components/switch.json
packages/design-data/relationships/checkbox.json
packages/design-data/relationships/switch.json
packages/design-data/visuals/checkbox.json
packages/design-data/visuals/switch.json
sdk/cli/src/main.rs
sdk/core/src/anatomy_suggest.rs
sdk/core/src/lib.rs
sdk/core/src/schema.rs
sdk/core/src/validate/rules/mod.rs
sdk/core/src/validate/rules/spec073.rs
sdk/core/src/validate/rules/spec074.rs
sdk/core/src/validate/rules/spec075.rs
sdk/core/src/visual.rs
sdk/core/tests/fixtures/recipe-snapshots.json
sdk/plugins/site/assets/index.html
sdk/plugins/site/assets/visual-runtime.js
sdk/wasm/test/fixtures/visual-golden/checkbox/all-on-dark-mobile.svg
sdk/wasm/test/fixtures/visual-golden/checkbox/default.svg
sdk/wasm/test/fixtures/visual-golden/checkbox/first-values-wireframe.svg
sdk/wasm/test/fixtures/visual-golden/switch/all-on-dark-mobile.svg
sdk/wasm/test/fixtures/visual-golden/switch/default.svg
sdk/wasm/test/fixtures/visual-golden/switch/first-values-wireframe.svg

@github-actions

Copy link
Copy Markdown
Contributor

🧩 Component Schema Changes Report

Component Schemas Changed (0 added, 0 deleted, 5 updated)

Original Branch: next/visual-recipes

✅ No Breaking Changes

This PR contains only non-breaking changes to component schemas.

🔄 Non-Breaking Updates

action-button

badge

button

checkbox

switch


This diff was generated automatically and contains only backward-compatible changes.


This comment was automatically generated by the component schema diff tool. 🤖

@github-actions

Copy link
Copy Markdown
Contributor

🎨 Token Changes Report

Tokens Changed (0)

Original Branch: next/visual-recipes


This comment was automatically generated by the token diff tool. 🤖

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant