@reqvire-org/ads 0.3.8 → 0.3.10

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 (43) hide show
  1. package/dist/atomic-trace.mjs +3 -198
  2. package/dist/bootstrap-ds/scripts/build-mcp-previews.mjs +2 -1
  3. package/dist/bootstrap-ds/vite.config.ts +2 -1
  4. package/dist/check.mjs +12 -3
  5. package/dist/linaria/atomic-css.cjs +2 -0
  6. package/dist/linaria/atomic-styled.cjs +2 -0
  7. package/dist/linaria/preserve-values.cjs +32 -0
  8. package/dist/linaria.d.mts +1 -0
  9. package/dist/linaria.mjs +9 -0
  10. package/dist/mcp/preview-widget.bundle.js +1 -1
  11. package/dist/mcp/resource-loader.js +5 -2
  12. package/dist/mcp/server.mjs +3 -1
  13. package/dist/preview-resources.mjs +2 -1
  14. package/dist/scenario-trace.mjs +149 -0
  15. package/dist/scenarios-compiler.mjs +2 -1
  16. package/dist/scenarios.mjs +13 -6
  17. package/dist/skills/ads-break-ui/SKILL.md +9 -2
  18. package/dist/skills/ads-break-ui/references/atomic-styles.md +50 -0
  19. package/dist/skills/ads-break-ui/references/scenarios.md +98 -0
  20. package/dist/skills/ads-designer/SKILL.md +12 -3
  21. package/dist/skills/ads-designer/assets/bootstrap-ds/scripts/build-mcp-previews.mjs +2 -1
  22. package/dist/skills/ads-designer/assets/bootstrap-ds/vite.config.ts +2 -1
  23. package/dist/skills/ads-designer/references/atomic-styles.md +50 -0
  24. package/dist/skills/ads-designer/references/scenarios.md +98 -0
  25. package/dist/skills/ads-import/SKILL.md +9 -2
  26. package/dist/skills/ads-import/references/atomic-styles.md +50 -0
  27. package/dist/skills/ads-import/references/scenarios.md +98 -0
  28. package/dist/skills/ads-migrate/SKILL.md +9 -2
  29. package/dist/skills/ads-migrate/references/atomic-styles.md +50 -0
  30. package/dist/skills/ads-migrate/references/scenarios.md +98 -0
  31. package/dist/skills/ads-motion/SKILL.md +9 -2
  32. package/dist/skills/ads-motion/references/atomic-styles.md +50 -0
  33. package/dist/skills/ads-motion/references/scenarios.md +98 -0
  34. package/dist/source-values.mjs +247 -0
  35. package/dist/verification/browser.mjs +21 -12
  36. package/dist/verification/playwright-reporter.cjs +6 -2
  37. package/dist/verification.mjs +13 -4
  38. package/docs/ADS.md +20 -5
  39. package/docs/ARCHITECTURE.md +18 -0
  40. package/docs/BEHAVIORS.md +11 -1
  41. package/docs/CHANGELOG.md +27 -1
  42. package/docs/MCP.md +16 -0
  43. package/package.json +10 -1
@@ -44,11 +44,18 @@ use the client's normal source-editing tools.
44
44
  For owner drafts, token-sample reconciliation, coupled transactions and local
45
45
  constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
46
46
 
47
- For atomic base/variant styling, helper/wrapper class composition, or an
47
+ For parent/child `covers`, public style-helper use in scenarios, or
48
+ `scenario-render` / `showcase-class` findings, read
49
+ [scenario contracts](references/scenarios.md). Traced parents can cover declared
50
+ public children; verified public Linaria helpers do not grant custom scenario CSS.
51
+
52
+ For atomic base/variant styling, helper/wrapper class composition, extracted
53
+ custom-property arithmetic, or an
48
54
  `atomic-composition-review` / `atomic-composition-limit` advisory, read
49
55
  [atomic style composition](references/atomic-styles.md). The same guide is served
50
56
  as `ads://guides/atomic-styles`. It explains shorthand/logical conflicts and
51
- matching-property fixes. Review warnings in the real `cx` composition and verify
57
+ matching-property fixes, plus the build resolver for preserving opaque custom
58
+ properties through extraction. Review warnings in the real `cx` composition and verify
52
59
  computed styles across affected sizes/states; retain intentional product behavior.
53
60
 
54
61
  Controllers are UI behavior owners: private helpers stay with their component or
@@ -81,6 +81,56 @@ const treatment = css`
81
81
  This is a distinct state, not two competing base atoms. Whether changing padding
82
82
  on hover is desirable remains a product decision.
83
83
 
84
+ ## Preserve custom-property arithmetic during extraction
85
+
86
+ Custom properties can hold an unevaluated token stream that becomes arithmetic
87
+ only after substitution into a later `calc()`. For example:
88
+
89
+ ```css
90
+ --i: 2;
91
+ --scale: var(--i) * 0.05 + 1;
92
+ transform: scale(calc(-1 * var(--scale)));
93
+ ```
94
+
95
+ The result is scale `0.9`: substitution does not add parentheses around the
96
+ custom property. Some Linaria/Stylis extraction versions strip the whitespace
97
+ around the bare `+`, leaving `0.05+1`. The browser then treats the transform as
98
+ invalid. This can happen with CSS minification disabled. Source guards cannot
99
+ prove what a later extractor emits.
100
+
101
+ Use ADS's build-only resolver in **both** the application's Linaria configuration
102
+ and its separately configured MCP preview builder:
103
+
104
+ ```js
105
+ import wyw from "@wyw-in-js/vite";
106
+ import { linariaTagResolver } from "@reqvire-org/ads/linaria";
107
+
108
+ // In the project's Vite plugins:
109
+ wyw({ tagResolver: linariaTagResolver });
110
+ ```
111
+
112
+ The resolver keeps the project's installed atomic processor and preserves opaque
113
+ custom-property values through its nesting/atomization pass. It does not add a
114
+ browser runtime or alter token ownership. Existing projects must adopt it in
115
+ each extraction pipeline; upgrading ADS alone does not rewrite custom builders.
116
+ If an existing `tagResolver` handles other tags, delegate atomic imports to
117
+ `linariaTagResolver(source, tag)` and retain the existing fallback. WyW config
118
+ files also support this resolver when a build integration requires serializable
119
+ inline options.
120
+
121
+ For a source workaround, write a self-contained formula and consume it directly:
122
+
123
+ ```css
124
+ --scale: calc(1 - var(--i) * 0.05);
125
+ transform: scale(var(--scale));
126
+ ```
127
+
128
+ This also produces `0.9`. Simply wrapping the old value in `calc()` while keeping
129
+ the outer `-1 *` changes its grouping and result. Verify extracted CSS text and a
130
+ computed style after any rewrite, including nested `var()` fallbacks/transforms.
131
+ Do not globally insert spaces into already extracted CSS: that can change valid
132
+ signed numbers, identifiers, strings or URLs.
133
+
84
134
  ## Follow helpers and forwarded classes
85
135
 
86
136
  Composition can cross a helper or a component boundary. For example, in component
@@ -0,0 +1,98 @@
1
+ # Scenario rendering, token previews and public class helpers
2
+
3
+ Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
4
+ diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
5
+
6
+ ## Owner-local token previews load their own definitions
7
+
8
+ Keep the registered token sheet imported by its runtime owner for product use.
9
+ A colocated `kind: "tokens"` scenario may render only the public review pattern
10
+ with its fixture samples. Discovery adds the registered owner sheet to the
11
+ generated record's `stylesheets`; `previewEntriesPlugin` imports those paths
12
+ into the token preview independently of the runtime component. Custom builders
13
+ that replace this plugin must preserve these explicit stylesheet dependencies.
14
+ Do not render the runtime owner merely to retain its CSS or add unrelated sheets.
15
+
16
+ Open the exact token scenario in a fresh App and verify resolved values and sample
17
+ effects in both themes. A successful ordinary component preview does not prove
18
+ the independently bundled token preview loads the same definitions. Shared
19
+ foundation styling still follows the project's mount/build integration.
20
+
21
+ ## Public children can share their parent's scenario
22
+
23
+ Declare the public parts actually demonstrated in `covers`, even when their
24
+ parent renders them internally:
25
+
26
+ ```tsx
27
+ // Runtime owner
28
+ export function Part() { return <span>Content</span>; }
29
+ export function Frame({ visible = true } = {}) {
30
+ return <section>{visible && <Part />}</section>;
31
+ }
32
+
33
+ // Colocated Scenario.tsx
34
+ import { Frame } from "@ds";
35
+ export const scenario = { title: "Frame", covers: ["Frame", "Part"] };
36
+ export default function Scenario() { return <Frame />; }
37
+ ```
38
+
39
+ ADS follows returned JSX through local components/helpers, aliases, registered
40
+ framework factories, memo/ref wrappers and context providers. Fixture props,
41
+ spreads and destructuring defaults select the child path. An explicit
42
+ `visible={false}` does not cover `Part`. When a condition remains unknown, only
43
+ parts returned on every possible path receive transitive credit. Imports, unused
44
+ JSX, event-handler bodies and uncalled functions do not establish child rendering.
45
+ Only the explicitly declared `covers` entries acquire coverage; dependencies are
46
+ not silently added to metadata or the catalogue.
47
+
48
+ Tracing is bounded and does not execute the project. Recursion, written/escaped inputs,
49
+ opaque external wrappers and unsupported control flow can prevent proof. The
50
+ diagnostic explains known limits. Use meaningful fixture states or another real
51
+ scenario; do not make a valid public part private or duplicate it in a parent
52
+ just to satisfy a guard. Static evidence does not establish successful mounting,
53
+ visibility, interaction, every state or visual parity. Verify those in the built
54
+ App and registered browser checks.
55
+
56
+ ## Scenarios may consume verified public style helpers
57
+
58
+ A deliberately public helper can expose its owner's Linaria treatment:
59
+
60
+ ```tsx
61
+ // Runtime owner
62
+ const treatment = css`padding-inline: var(--space-4);`;
63
+ export function controlClasses() {
64
+ return cx("control-hook", treatment);
65
+ }
66
+
67
+ // Scenario: consume the public API; define no styles here
68
+ <PublicLink className={controlClasses()}>Documentation</PublicLink>
69
+ ```
70
+
71
+ The sample token and APIs are illustrative; use the project's real exports and
72
+ tokens. Import helpers through the public ADS entry. ADS traces helper calls,
73
+ returns, local aliases, finite known selections and Linaria `cx` composition.
74
+ Styling must originate in component/pattern Linaria through a public callable
75
+ helper. A literal stable hook authored in that runtime owner may accompany the
76
+ verified styles. Each nonempty return path needs actual Linaria declarations;
77
+ empty templates and hook-only/string-only returns do not qualify.
78
+
79
+ These are still rejected:
80
+
81
+ ```tsx
82
+ <PublicLink className="custom-layout" />
83
+ <PublicLink className={arbitraryPublicFunctionReturningAString()} />
84
+ <PublicLink className={controlClasses({ className: "custom-layout" })} />
85
+ ```
86
+
87
+ Scenario-supplied strings, generated styles in fixtures, private style imports,
88
+ spoofed Linaria functions and untraceable results acquire no permission by being
89
+ passed through a public function. Known className values in props/spreads receive
90
+ the same provenance check. Opaque spreads remain outside complete source proof.
91
+ An `exercises` entry records behavioral use; it never grants styling permission.
92
+
93
+ Keep helper signatures compatible with the product API. Fix ownership/provenance
94
+ in the runtime owner when genuinely wrong; retain intentional public APIs when
95
+ reporting an unsupported trace. Demo-only sizing, framing and arrangement still
96
+ belong in public review/layout patterns. A style helper is not permission to
97
+ author a second design in the scenario. For cascade risks and extraction issues,
98
+ read [atomic-styles.md](atomic-styles.md).
@@ -46,11 +46,18 @@ For owner drafts, token-sample reconciliation, coupled transactions and local
46
46
  constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
47
47
 
48
48
 
49
- For atomic base/variant styling, helper/wrapper class composition, or an
49
+ For parent/child `covers`, public style-helper use in scenarios, or
50
+ `scenario-render` / `showcase-class` findings, read
51
+ [scenario contracts](references/scenarios.md). Traced parents can cover declared
52
+ public children; verified public Linaria helpers do not grant custom scenario CSS.
53
+
54
+ For atomic base/variant styling, helper/wrapper class composition, extracted
55
+ custom-property arithmetic, or an
50
56
  `atomic-composition-review` / `atomic-composition-limit` advisory, read
51
57
  [atomic style composition](references/atomic-styles.md). The same guide is served
52
58
  as `ads://guides/atomic-styles`. It explains shorthand/logical conflicts and
53
- matching-property fixes. Review warnings in the real `cx` composition and verify
59
+ matching-property fixes, plus the build resolver for preserving opaque custom
60
+ properties through extraction. Review warnings in the real `cx` composition and verify
54
61
  computed styles across affected sizes/states; retain intentional product behavior.
55
62
 
56
63
  Controllers are UI behavior owners: private helpers stay with their component or
@@ -81,6 +81,56 @@ const treatment = css`
81
81
  This is a distinct state, not two competing base atoms. Whether changing padding
82
82
  on hover is desirable remains a product decision.
83
83
 
84
+ ## Preserve custom-property arithmetic during extraction
85
+
86
+ Custom properties can hold an unevaluated token stream that becomes arithmetic
87
+ only after substitution into a later `calc()`. For example:
88
+
89
+ ```css
90
+ --i: 2;
91
+ --scale: var(--i) * 0.05 + 1;
92
+ transform: scale(calc(-1 * var(--scale)));
93
+ ```
94
+
95
+ The result is scale `0.9`: substitution does not add parentheses around the
96
+ custom property. Some Linaria/Stylis extraction versions strip the whitespace
97
+ around the bare `+`, leaving `0.05+1`. The browser then treats the transform as
98
+ invalid. This can happen with CSS minification disabled. Source guards cannot
99
+ prove what a later extractor emits.
100
+
101
+ Use ADS's build-only resolver in **both** the application's Linaria configuration
102
+ and its separately configured MCP preview builder:
103
+
104
+ ```js
105
+ import wyw from "@wyw-in-js/vite";
106
+ import { linariaTagResolver } from "@reqvire-org/ads/linaria";
107
+
108
+ // In the project's Vite plugins:
109
+ wyw({ tagResolver: linariaTagResolver });
110
+ ```
111
+
112
+ The resolver keeps the project's installed atomic processor and preserves opaque
113
+ custom-property values through its nesting/atomization pass. It does not add a
114
+ browser runtime or alter token ownership. Existing projects must adopt it in
115
+ each extraction pipeline; upgrading ADS alone does not rewrite custom builders.
116
+ If an existing `tagResolver` handles other tags, delegate atomic imports to
117
+ `linariaTagResolver(source, tag)` and retain the existing fallback. WyW config
118
+ files also support this resolver when a build integration requires serializable
119
+ inline options.
120
+
121
+ For a source workaround, write a self-contained formula and consume it directly:
122
+
123
+ ```css
124
+ --scale: calc(1 - var(--i) * 0.05);
125
+ transform: scale(var(--scale));
126
+ ```
127
+
128
+ This also produces `0.9`. Simply wrapping the old value in `calc()` while keeping
129
+ the outer `-1 *` changes its grouping and result. Verify extracted CSS text and a
130
+ computed style after any rewrite, including nested `var()` fallbacks/transforms.
131
+ Do not globally insert spaces into already extracted CSS: that can change valid
132
+ signed numbers, identifiers, strings or URLs.
133
+
84
134
  ## Follow helpers and forwarded classes
85
135
 
86
136
  Composition can cross a helper or a component boundary. For example, in component
@@ -0,0 +1,98 @@
1
+ # Scenario rendering, token previews and public class helpers
2
+
3
+ Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
4
+ diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
5
+
6
+ ## Owner-local token previews load their own definitions
7
+
8
+ Keep the registered token sheet imported by its runtime owner for product use.
9
+ A colocated `kind: "tokens"` scenario may render only the public review pattern
10
+ with its fixture samples. Discovery adds the registered owner sheet to the
11
+ generated record's `stylesheets`; `previewEntriesPlugin` imports those paths
12
+ into the token preview independently of the runtime component. Custom builders
13
+ that replace this plugin must preserve these explicit stylesheet dependencies.
14
+ Do not render the runtime owner merely to retain its CSS or add unrelated sheets.
15
+
16
+ Open the exact token scenario in a fresh App and verify resolved values and sample
17
+ effects in both themes. A successful ordinary component preview does not prove
18
+ the independently bundled token preview loads the same definitions. Shared
19
+ foundation styling still follows the project's mount/build integration.
20
+
21
+ ## Public children can share their parent's scenario
22
+
23
+ Declare the public parts actually demonstrated in `covers`, even when their
24
+ parent renders them internally:
25
+
26
+ ```tsx
27
+ // Runtime owner
28
+ export function Part() { return <span>Content</span>; }
29
+ export function Frame({ visible = true } = {}) {
30
+ return <section>{visible && <Part />}</section>;
31
+ }
32
+
33
+ // Colocated Scenario.tsx
34
+ import { Frame } from "@ds";
35
+ export const scenario = { title: "Frame", covers: ["Frame", "Part"] };
36
+ export default function Scenario() { return <Frame />; }
37
+ ```
38
+
39
+ ADS follows returned JSX through local components/helpers, aliases, registered
40
+ framework factories, memo/ref wrappers and context providers. Fixture props,
41
+ spreads and destructuring defaults select the child path. An explicit
42
+ `visible={false}` does not cover `Part`. When a condition remains unknown, only
43
+ parts returned on every possible path receive transitive credit. Imports, unused
44
+ JSX, event-handler bodies and uncalled functions do not establish child rendering.
45
+ Only the explicitly declared `covers` entries acquire coverage; dependencies are
46
+ not silently added to metadata or the catalogue.
47
+
48
+ Tracing is bounded and does not execute the project. Recursion, written/escaped inputs,
49
+ opaque external wrappers and unsupported control flow can prevent proof. The
50
+ diagnostic explains known limits. Use meaningful fixture states or another real
51
+ scenario; do not make a valid public part private or duplicate it in a parent
52
+ just to satisfy a guard. Static evidence does not establish successful mounting,
53
+ visibility, interaction, every state or visual parity. Verify those in the built
54
+ App and registered browser checks.
55
+
56
+ ## Scenarios may consume verified public style helpers
57
+
58
+ A deliberately public helper can expose its owner's Linaria treatment:
59
+
60
+ ```tsx
61
+ // Runtime owner
62
+ const treatment = css`padding-inline: var(--space-4);`;
63
+ export function controlClasses() {
64
+ return cx("control-hook", treatment);
65
+ }
66
+
67
+ // Scenario: consume the public API; define no styles here
68
+ <PublicLink className={controlClasses()}>Documentation</PublicLink>
69
+ ```
70
+
71
+ The sample token and APIs are illustrative; use the project's real exports and
72
+ tokens. Import helpers through the public ADS entry. ADS traces helper calls,
73
+ returns, local aliases, finite known selections and Linaria `cx` composition.
74
+ Styling must originate in component/pattern Linaria through a public callable
75
+ helper. A literal stable hook authored in that runtime owner may accompany the
76
+ verified styles. Each nonempty return path needs actual Linaria declarations;
77
+ empty templates and hook-only/string-only returns do not qualify.
78
+
79
+ These are still rejected:
80
+
81
+ ```tsx
82
+ <PublicLink className="custom-layout" />
83
+ <PublicLink className={arbitraryPublicFunctionReturningAString()} />
84
+ <PublicLink className={controlClasses({ className: "custom-layout" })} />
85
+ ```
86
+
87
+ Scenario-supplied strings, generated styles in fixtures, private style imports,
88
+ spoofed Linaria functions and untraceable results acquire no permission by being
89
+ passed through a public function. Known className values in props/spreads receive
90
+ the same provenance check. Opaque spreads remain outside complete source proof.
91
+ An `exercises` entry records behavioral use; it never grants styling permission.
92
+
93
+ Keep helper signatures compatible with the product API. Fix ownership/provenance
94
+ in the runtime owner when genuinely wrong; retain intentional public APIs when
95
+ reporting an unsupported trace. Demo-only sizing, framing and arrangement still
96
+ belong in public review/layout patterns. A style helper is not permission to
97
+ author a second design in the scenario. For cascade risks and extraction issues,
98
+ read [atomic-styles.md](atomic-styles.md).
@@ -66,11 +66,18 @@ For owner drafts, token-sample reconciliation, coupled transactions and local
66
66
  constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
67
67
 
68
68
 
69
- For atomic base/variant styling, helper/wrapper class composition, or an
69
+ For parent/child `covers`, public style-helper use in scenarios, or
70
+ `scenario-render` / `showcase-class` findings, read
71
+ [scenario contracts](references/scenarios.md). Traced parents can cover declared
72
+ public children; verified public Linaria helpers do not grant custom scenario CSS.
73
+
74
+ For atomic base/variant styling, helper/wrapper class composition, extracted
75
+ custom-property arithmetic, or an
70
76
  `atomic-composition-review` / `atomic-composition-limit` advisory, read
71
77
  [atomic style composition](references/atomic-styles.md). The same guide is served
72
78
  as `ads://guides/atomic-styles`. It explains shorthand/logical conflicts and
73
- matching-property fixes. Review warnings in the real `cx` composition and verify
79
+ matching-property fixes, plus the build resolver for preserving opaque custom
80
+ properties through extraction. Review warnings in the real `cx` composition and verify
74
81
  computed styles across affected sizes/states; retain intentional product behavior.
75
82
 
76
83
  Controllers are UI behavior owners: private helpers stay with their component or
@@ -81,6 +81,56 @@ const treatment = css`
81
81
  This is a distinct state, not two competing base atoms. Whether changing padding
82
82
  on hover is desirable remains a product decision.
83
83
 
84
+ ## Preserve custom-property arithmetic during extraction
85
+
86
+ Custom properties can hold an unevaluated token stream that becomes arithmetic
87
+ only after substitution into a later `calc()`. For example:
88
+
89
+ ```css
90
+ --i: 2;
91
+ --scale: var(--i) * 0.05 + 1;
92
+ transform: scale(calc(-1 * var(--scale)));
93
+ ```
94
+
95
+ The result is scale `0.9`: substitution does not add parentheses around the
96
+ custom property. Some Linaria/Stylis extraction versions strip the whitespace
97
+ around the bare `+`, leaving `0.05+1`. The browser then treats the transform as
98
+ invalid. This can happen with CSS minification disabled. Source guards cannot
99
+ prove what a later extractor emits.
100
+
101
+ Use ADS's build-only resolver in **both** the application's Linaria configuration
102
+ and its separately configured MCP preview builder:
103
+
104
+ ```js
105
+ import wyw from "@wyw-in-js/vite";
106
+ import { linariaTagResolver } from "@reqvire-org/ads/linaria";
107
+
108
+ // In the project's Vite plugins:
109
+ wyw({ tagResolver: linariaTagResolver });
110
+ ```
111
+
112
+ The resolver keeps the project's installed atomic processor and preserves opaque
113
+ custom-property values through its nesting/atomization pass. It does not add a
114
+ browser runtime or alter token ownership. Existing projects must adopt it in
115
+ each extraction pipeline; upgrading ADS alone does not rewrite custom builders.
116
+ If an existing `tagResolver` handles other tags, delegate atomic imports to
117
+ `linariaTagResolver(source, tag)` and retain the existing fallback. WyW config
118
+ files also support this resolver when a build integration requires serializable
119
+ inline options.
120
+
121
+ For a source workaround, write a self-contained formula and consume it directly:
122
+
123
+ ```css
124
+ --scale: calc(1 - var(--i) * 0.05);
125
+ transform: scale(var(--scale));
126
+ ```
127
+
128
+ This also produces `0.9`. Simply wrapping the old value in `calc()` while keeping
129
+ the outer `-1 *` changes its grouping and result. Verify extracted CSS text and a
130
+ computed style after any rewrite, including nested `var()` fallbacks/transforms.
131
+ Do not globally insert spaces into already extracted CSS: that can change valid
132
+ signed numbers, identifiers, strings or URLs.
133
+
84
134
  ## Follow helpers and forwarded classes
85
135
 
86
136
  Composition can cross a helper or a component boundary. For example, in component
@@ -0,0 +1,98 @@
1
+ # Scenario rendering, token previews and public class helpers
2
+
3
+ Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
4
+ diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
5
+
6
+ ## Owner-local token previews load their own definitions
7
+
8
+ Keep the registered token sheet imported by its runtime owner for product use.
9
+ A colocated `kind: "tokens"` scenario may render only the public review pattern
10
+ with its fixture samples. Discovery adds the registered owner sheet to the
11
+ generated record's `stylesheets`; `previewEntriesPlugin` imports those paths
12
+ into the token preview independently of the runtime component. Custom builders
13
+ that replace this plugin must preserve these explicit stylesheet dependencies.
14
+ Do not render the runtime owner merely to retain its CSS or add unrelated sheets.
15
+
16
+ Open the exact token scenario in a fresh App and verify resolved values and sample
17
+ effects in both themes. A successful ordinary component preview does not prove
18
+ the independently bundled token preview loads the same definitions. Shared
19
+ foundation styling still follows the project's mount/build integration.
20
+
21
+ ## Public children can share their parent's scenario
22
+
23
+ Declare the public parts actually demonstrated in `covers`, even when their
24
+ parent renders them internally:
25
+
26
+ ```tsx
27
+ // Runtime owner
28
+ export function Part() { return <span>Content</span>; }
29
+ export function Frame({ visible = true } = {}) {
30
+ return <section>{visible && <Part />}</section>;
31
+ }
32
+
33
+ // Colocated Scenario.tsx
34
+ import { Frame } from "@ds";
35
+ export const scenario = { title: "Frame", covers: ["Frame", "Part"] };
36
+ export default function Scenario() { return <Frame />; }
37
+ ```
38
+
39
+ ADS follows returned JSX through local components/helpers, aliases, registered
40
+ framework factories, memo/ref wrappers and context providers. Fixture props,
41
+ spreads and destructuring defaults select the child path. An explicit
42
+ `visible={false}` does not cover `Part`. When a condition remains unknown, only
43
+ parts returned on every possible path receive transitive credit. Imports, unused
44
+ JSX, event-handler bodies and uncalled functions do not establish child rendering.
45
+ Only the explicitly declared `covers` entries acquire coverage; dependencies are
46
+ not silently added to metadata or the catalogue.
47
+
48
+ Tracing is bounded and does not execute the project. Recursion, written/escaped inputs,
49
+ opaque external wrappers and unsupported control flow can prevent proof. The
50
+ diagnostic explains known limits. Use meaningful fixture states or another real
51
+ scenario; do not make a valid public part private or duplicate it in a parent
52
+ just to satisfy a guard. Static evidence does not establish successful mounting,
53
+ visibility, interaction, every state or visual parity. Verify those in the built
54
+ App and registered browser checks.
55
+
56
+ ## Scenarios may consume verified public style helpers
57
+
58
+ A deliberately public helper can expose its owner's Linaria treatment:
59
+
60
+ ```tsx
61
+ // Runtime owner
62
+ const treatment = css`padding-inline: var(--space-4);`;
63
+ export function controlClasses() {
64
+ return cx("control-hook", treatment);
65
+ }
66
+
67
+ // Scenario: consume the public API; define no styles here
68
+ <PublicLink className={controlClasses()}>Documentation</PublicLink>
69
+ ```
70
+
71
+ The sample token and APIs are illustrative; use the project's real exports and
72
+ tokens. Import helpers through the public ADS entry. ADS traces helper calls,
73
+ returns, local aliases, finite known selections and Linaria `cx` composition.
74
+ Styling must originate in component/pattern Linaria through a public callable
75
+ helper. A literal stable hook authored in that runtime owner may accompany the
76
+ verified styles. Each nonempty return path needs actual Linaria declarations;
77
+ empty templates and hook-only/string-only returns do not qualify.
78
+
79
+ These are still rejected:
80
+
81
+ ```tsx
82
+ <PublicLink className="custom-layout" />
83
+ <PublicLink className={arbitraryPublicFunctionReturningAString()} />
84
+ <PublicLink className={controlClasses({ className: "custom-layout" })} />
85
+ ```
86
+
87
+ Scenario-supplied strings, generated styles in fixtures, private style imports,
88
+ spoofed Linaria functions and untraceable results acquire no permission by being
89
+ passed through a public function. Known className values in props/spreads receive
90
+ the same provenance check. Opaque spreads remain outside complete source proof.
91
+ An `exercises` entry records behavioral use; it never grants styling permission.
92
+
93
+ Keep helper signatures compatible with the product API. Fix ownership/provenance
94
+ in the runtime owner when genuinely wrong; retain intentional public APIs when
95
+ reporting an unsupported trace. Demo-only sizing, framing and arrangement still
96
+ belong in public review/layout patterns. A style helper is not permission to
97
+ author a second design in the scenario. For cascade risks and extraction issues,
98
+ read [atomic-styles.md](atomic-styles.md).