@reqvire-org/ads 0.3.6 → 0.3.8

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,186 @@
1
+ # Atomic style composition
2
+
3
+ Use this guide when creating or migrating component/pattern styles, changing
4
+ base/size/state combinations, or reviewing `atomic-composition-review` warnings.
5
+ It is also available as `ads://guides/atomic-styles` through ADS MCP.
6
+
7
+ ## Why valid tokens can still render incorrectly
8
+
9
+ Atomic Linaria extracts declarations into reusable classes. `cx` from
10
+ `@linaria/atomic` or `@linaria/core` replaces earlier atoms with the same property
11
+ and selector/condition key. It does not expand every CSS shorthand or resolve
12
+ every overlap between physical and logical properties.
13
+
14
+ For example, these declarations have different atomic keys:
15
+
16
+ ```tsx
17
+ const base = css`
18
+ padding: 0;
19
+ `;
20
+ const small = css`
21
+ padding-inline: var(--space-6);
22
+ `;
23
+
24
+ cx(base, small);
25
+ ```
26
+
27
+ Both classes survive. Both declarations can affect horizontal padding in a
28
+ horizontal writing mode. In the inspected Linaria implementation, `padding` and
29
+ `padding-inline` receive equal specificity. If a reset atom is emitted later,
30
+ it can override the intended size. Shared atom reuse and CSS splitting can make
31
+ this visible in a larger build even when an isolated view appears correct.
32
+ The order of class names in HTML does not decide equal-specificity rule order.
33
+ Valid tokens, successful extraction and a passing source check do not establish
34
+ the intended computed value.
35
+
36
+ See Linaria's [class merging implementation](https://github.com/callstack/linaria/blob/master/packages/core/src/cx.ts)
37
+ and [property priority implementation](https://github.com/callstack/linaria/blob/master/packages/atomic/src/processors/helpers/propertyPriority.ts).
38
+ Inspect the project's installed version when investigating its output.
39
+
40
+ ## Prefer matching properties across composed blocks
41
+
42
+ Express the reset and overrides using the same property vocabulary:
43
+
44
+ ```tsx
45
+ const base = css`
46
+ padding-block: 0;
47
+ padding-inline: 0;
48
+ `;
49
+ const small = css`
50
+ padding-inline: var(--space-6);
51
+ `;
52
+ const regular = css`
53
+ padding-block: var(--space-4);
54
+ padding-inline: var(--space-8);
55
+ `;
56
+
57
+ cx(base, compact ? small : regular);
58
+ ```
59
+
60
+ Now each selected size replaces the corresponding base atom through `cx`.
61
+ Review every size, including the default and icon-only variants. Changing only
62
+ one size can leave another size mixing shorthand and logical properties.
63
+ The names and tokens above are illustrative: use the project's real API and
64
+ declared tokens. Preserve its intended dimensions and supported writing modes.
65
+
66
+ The same reasoning applies to margin, inset, logical borders/corners, dimensions
67
+ and overflow. For example, prefer `margin-inline: 0` plus a size's
68
+ `margin-inline: var(...)` over combining `margin: 0` with that logical override.
69
+ Choose consistent physical properties when the product deliberately positions
70
+ against physical edges; logical properties are not mandatory.
71
+
72
+ An intentional state override may have a different selector or condition:
73
+
74
+ ```tsx
75
+ const treatment = css`
76
+ padding-inline: var(--space-6);
77
+ &:hover { padding-inline: var(--space-8); }
78
+ `;
79
+ ```
80
+
81
+ This is a distinct state, not two competing base atoms. Whether changing padding
82
+ on hover is desirable remains a product decision.
83
+
84
+ ## Follow helpers and forwarded classes
85
+
86
+ Composition can cross a helper or a component boundary. For example, in component
87
+ implementation source:
88
+
89
+ ```tsx
90
+ function baseClasses() { return base; }
91
+ function Primitive({ className, ...props }) {
92
+ return <button {...props} className={cx(baseClasses(), className)} />;
93
+ }
94
+ function CompactPrimitive(props) {
95
+ return <Primitive {...props} className={small} />;
96
+ }
97
+ ```
98
+
99
+ The base and small atoms can reach the same button. Inspect both owners when
100
+ correcting their property vocabulary. The wrapper's class does not style every
101
+ descendant: a class on a child or sibling element is a separate composition.
102
+ An imported stylesheet alone does not show that its classes co-apply.
103
+
104
+ Spread order matters. `<button className={base} {...props} />` can replace the
105
+ entire className; `<button {...props} className={cx(base, className)} />` composes
106
+ it explicitly. Keep the product's intended forwarding behavior when fixing an
107
+ overlap. Do not change the public API simply to make tracing easier.
108
+
109
+ Warnings include a bounded `composition` path through traced helpers and
110
+ components. A `target` identifies a statically reached DOM element. This
111
+ establishes source composition, not that a scenario mounted it or that its
112
+ computed result is wrong. `writingModeDependent: true` identifies overlaps that
113
+ change with direction or writing mode; evaluate those against supported modes.
114
+ Literal overlaps with provably equal values are omitted where the analyzer can
115
+ expand them safely. Token formulas, inheritance and runtime values still need
116
+ review. A margin shorthand and `margin-inline: auto` may agree horizontally but
117
+ disagree in vertical text, so horizontal equality alone is insufficient.
118
+
119
+ ## Respond to a warning
120
+
121
+ 1. Follow the warning's related file/line locations and inspect the actual `cx`
122
+ composition. Variant lookups may contribute several possible combinations.
123
+ 2. In a current built preview, inspect computed properties and the winning CSS
124
+ rules. Establish whether extraction order, specificity, writing mode or an
125
+ intentional override explains the result.
126
+ 3. For accidental overlap, align property names/granularity across the base and
127
+ affected variants. Use Linaria's `cx`, preserve tokens and fix the owning
128
+ component/pattern. Reordering class strings does not remove overlapping keys.
129
+ 4. Verify the affected sizes/states and supported directions in the normal app
130
+ and preview build. Add a registered rendered check when a specific geometry
131
+ or computed-style guarantee matters.
132
+
133
+ Increasing specificity, adding `!important`, copying styles into scenarios or
134
+ moving component styling into `base.css` can hide the symptom while retaining
135
+ the conflict. Prefer resolving the composition itself. If an overlap is
136
+ intentional, document why its precedence is stable and verify the resulting
137
+ behavior rather than changing product capabilities to silence a warning.
138
+
139
+ Use existing behavior contracts and `ads_verify` for important geometry. Register
140
+ a check beside its owner, link its real scenario and use the project's browser
141
+ profile. An assertion can inspect the actual control in the App frame:
142
+
143
+ ```ts
144
+ const frame = await openBehaviorScenario(page, "compact-spacing");
145
+ await expect(frame.getByRole("button", { name: "Compact" }))
146
+ .toHaveCSS("padding-inline-start", "8px");
147
+ ```
148
+
149
+ The name, check ID and expected value above are examples. Derive assertions from
150
+ the project's intended API and design, with relevant variants, open/hover/focus
151
+ states, themes and supported writing modes. Wait for observable readiness; an
152
+ event-stream connection can prevent `networkidle` from settling. A generic
153
+ overlap scan cannot decide which dimensions the product intended. A failed
154
+ registered geometry assertion is blocking through the existing verification
155
+ contract; an overlap warning remains a review signal.
156
+
157
+ ## What ADS checks
158
+
159
+ `atomic-composition-review` is a nonblocking warning, returned under `advisories`
160
+ with `severity: "warning"`. CLI checks still exit successfully when there are no
161
+ errors; MCP checks and mutations preserve the warning and its guidance URI.
162
+
163
+ The source review examines atomic Linaria templates and statically traceable
164
+ `cx` arguments, including aliases, local imports/re-exports, local helper returns,
165
+ arguments/defaults, nested composition, conditional expressions and variant-object
166
+ lookups. It follows explicit `className` forwarding through local function
167
+ components, props/rest spreads and imported React/Preact `memo`/`forwardRef`
168
+ wrappers to an intrinsic JSX element. It checks known overlaps involving box
169
+ spacing, inset, borders/corners, dimensions, overflow, backgrounds, typography,
170
+ motion and common layout shorthands, plus `all` resets. It compares shared selector/condition contexts; separate alternatives
171
+ within one conditional or lookup are not assumed to apply together. Matching
172
+ atomic property/selector/condition keys are replaced during traced `cx`
173
+ composition before comparing the surviving declarations.
174
+
175
+ This is a bounded source review, not a CSS engine or a proof of precedence. It
176
+ does not execute helpers or import project modules, enumerate every external
177
+ class, or model arbitrary runtime mutation, component rendering, selectors or
178
+ overlapping media queries. Recursive calls, unsupported call/control-flow paths,
179
+ unresolved DOM targets and traversal limits produce bounded
180
+ `atomic-composition-limit` informational advisories where known atomic styles
181
+ reach an unresolved composition. Ordinary externally supplied className values
182
+ remain open inputs, not guaranteed safe styles. Depth, work and alternative
183
+ limits keep source inspection bounded; an unreported path or an empty warning
184
+ list does not establish visual correctness. Actual failed registered
185
+ browser/behavior checks remain blocking; potentially intentional source overlaps
186
+ remain warnings.
@@ -46,6 +46,13 @@ 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
50
+ `atomic-composition-review` / `atomic-composition-limit` advisory, read
51
+ [atomic style composition](references/atomic-styles.md). The same guide is served
52
+ as `ads://guides/atomic-styles`. It explains shorthand/logical conflicts and
53
+ matching-property fixes. Review warnings in the real `cx` composition and verify
54
+ computed styles across affected sizes/states; retain intentional product behavior.
55
+
49
56
  Controllers are UI behavior owners: private helpers stay with their component or
50
57
  pattern; reusable controllers use discovered `controllers/<Name>` units. Use the
51
58
  project's configured framework and declared dependencies, or plain TypeScript,
@@ -0,0 +1,186 @@
1
+ # Atomic style composition
2
+
3
+ Use this guide when creating or migrating component/pattern styles, changing
4
+ base/size/state combinations, or reviewing `atomic-composition-review` warnings.
5
+ It is also available as `ads://guides/atomic-styles` through ADS MCP.
6
+
7
+ ## Why valid tokens can still render incorrectly
8
+
9
+ Atomic Linaria extracts declarations into reusable classes. `cx` from
10
+ `@linaria/atomic` or `@linaria/core` replaces earlier atoms with the same property
11
+ and selector/condition key. It does not expand every CSS shorthand or resolve
12
+ every overlap between physical and logical properties.
13
+
14
+ For example, these declarations have different atomic keys:
15
+
16
+ ```tsx
17
+ const base = css`
18
+ padding: 0;
19
+ `;
20
+ const small = css`
21
+ padding-inline: var(--space-6);
22
+ `;
23
+
24
+ cx(base, small);
25
+ ```
26
+
27
+ Both classes survive. Both declarations can affect horizontal padding in a
28
+ horizontal writing mode. In the inspected Linaria implementation, `padding` and
29
+ `padding-inline` receive equal specificity. If a reset atom is emitted later,
30
+ it can override the intended size. Shared atom reuse and CSS splitting can make
31
+ this visible in a larger build even when an isolated view appears correct.
32
+ The order of class names in HTML does not decide equal-specificity rule order.
33
+ Valid tokens, successful extraction and a passing source check do not establish
34
+ the intended computed value.
35
+
36
+ See Linaria's [class merging implementation](https://github.com/callstack/linaria/blob/master/packages/core/src/cx.ts)
37
+ and [property priority implementation](https://github.com/callstack/linaria/blob/master/packages/atomic/src/processors/helpers/propertyPriority.ts).
38
+ Inspect the project's installed version when investigating its output.
39
+
40
+ ## Prefer matching properties across composed blocks
41
+
42
+ Express the reset and overrides using the same property vocabulary:
43
+
44
+ ```tsx
45
+ const base = css`
46
+ padding-block: 0;
47
+ padding-inline: 0;
48
+ `;
49
+ const small = css`
50
+ padding-inline: var(--space-6);
51
+ `;
52
+ const regular = css`
53
+ padding-block: var(--space-4);
54
+ padding-inline: var(--space-8);
55
+ `;
56
+
57
+ cx(base, compact ? small : regular);
58
+ ```
59
+
60
+ Now each selected size replaces the corresponding base atom through `cx`.
61
+ Review every size, including the default and icon-only variants. Changing only
62
+ one size can leave another size mixing shorthand and logical properties.
63
+ The names and tokens above are illustrative: use the project's real API and
64
+ declared tokens. Preserve its intended dimensions and supported writing modes.
65
+
66
+ The same reasoning applies to margin, inset, logical borders/corners, dimensions
67
+ and overflow. For example, prefer `margin-inline: 0` plus a size's
68
+ `margin-inline: var(...)` over combining `margin: 0` with that logical override.
69
+ Choose consistent physical properties when the product deliberately positions
70
+ against physical edges; logical properties are not mandatory.
71
+
72
+ An intentional state override may have a different selector or condition:
73
+
74
+ ```tsx
75
+ const treatment = css`
76
+ padding-inline: var(--space-6);
77
+ &:hover { padding-inline: var(--space-8); }
78
+ `;
79
+ ```
80
+
81
+ This is a distinct state, not two competing base atoms. Whether changing padding
82
+ on hover is desirable remains a product decision.
83
+
84
+ ## Follow helpers and forwarded classes
85
+
86
+ Composition can cross a helper or a component boundary. For example, in component
87
+ implementation source:
88
+
89
+ ```tsx
90
+ function baseClasses() { return base; }
91
+ function Primitive({ className, ...props }) {
92
+ return <button {...props} className={cx(baseClasses(), className)} />;
93
+ }
94
+ function CompactPrimitive(props) {
95
+ return <Primitive {...props} className={small} />;
96
+ }
97
+ ```
98
+
99
+ The base and small atoms can reach the same button. Inspect both owners when
100
+ correcting their property vocabulary. The wrapper's class does not style every
101
+ descendant: a class on a child or sibling element is a separate composition.
102
+ An imported stylesheet alone does not show that its classes co-apply.
103
+
104
+ Spread order matters. `<button className={base} {...props} />` can replace the
105
+ entire className; `<button {...props} className={cx(base, className)} />` composes
106
+ it explicitly. Keep the product's intended forwarding behavior when fixing an
107
+ overlap. Do not change the public API simply to make tracing easier.
108
+
109
+ Warnings include a bounded `composition` path through traced helpers and
110
+ components. A `target` identifies a statically reached DOM element. This
111
+ establishes source composition, not that a scenario mounted it or that its
112
+ computed result is wrong. `writingModeDependent: true` identifies overlaps that
113
+ change with direction or writing mode; evaluate those against supported modes.
114
+ Literal overlaps with provably equal values are omitted where the analyzer can
115
+ expand them safely. Token formulas, inheritance and runtime values still need
116
+ review. A margin shorthand and `margin-inline: auto` may agree horizontally but
117
+ disagree in vertical text, so horizontal equality alone is insufficient.
118
+
119
+ ## Respond to a warning
120
+
121
+ 1. Follow the warning's related file/line locations and inspect the actual `cx`
122
+ composition. Variant lookups may contribute several possible combinations.
123
+ 2. In a current built preview, inspect computed properties and the winning CSS
124
+ rules. Establish whether extraction order, specificity, writing mode or an
125
+ intentional override explains the result.
126
+ 3. For accidental overlap, align property names/granularity across the base and
127
+ affected variants. Use Linaria's `cx`, preserve tokens and fix the owning
128
+ component/pattern. Reordering class strings does not remove overlapping keys.
129
+ 4. Verify the affected sizes/states and supported directions in the normal app
130
+ and preview build. Add a registered rendered check when a specific geometry
131
+ or computed-style guarantee matters.
132
+
133
+ Increasing specificity, adding `!important`, copying styles into scenarios or
134
+ moving component styling into `base.css` can hide the symptom while retaining
135
+ the conflict. Prefer resolving the composition itself. If an overlap is
136
+ intentional, document why its precedence is stable and verify the resulting
137
+ behavior rather than changing product capabilities to silence a warning.
138
+
139
+ Use existing behavior contracts and `ads_verify` for important geometry. Register
140
+ a check beside its owner, link its real scenario and use the project's browser
141
+ profile. An assertion can inspect the actual control in the App frame:
142
+
143
+ ```ts
144
+ const frame = await openBehaviorScenario(page, "compact-spacing");
145
+ await expect(frame.getByRole("button", { name: "Compact" }))
146
+ .toHaveCSS("padding-inline-start", "8px");
147
+ ```
148
+
149
+ The name, check ID and expected value above are examples. Derive assertions from
150
+ the project's intended API and design, with relevant variants, open/hover/focus
151
+ states, themes and supported writing modes. Wait for observable readiness; an
152
+ event-stream connection can prevent `networkidle` from settling. A generic
153
+ overlap scan cannot decide which dimensions the product intended. A failed
154
+ registered geometry assertion is blocking through the existing verification
155
+ contract; an overlap warning remains a review signal.
156
+
157
+ ## What ADS checks
158
+
159
+ `atomic-composition-review` is a nonblocking warning, returned under `advisories`
160
+ with `severity: "warning"`. CLI checks still exit successfully when there are no
161
+ errors; MCP checks and mutations preserve the warning and its guidance URI.
162
+
163
+ The source review examines atomic Linaria templates and statically traceable
164
+ `cx` arguments, including aliases, local imports/re-exports, local helper returns,
165
+ arguments/defaults, nested composition, conditional expressions and variant-object
166
+ lookups. It follows explicit `className` forwarding through local function
167
+ components, props/rest spreads and imported React/Preact `memo`/`forwardRef`
168
+ wrappers to an intrinsic JSX element. It checks known overlaps involving box
169
+ spacing, inset, borders/corners, dimensions, overflow, backgrounds, typography,
170
+ motion and common layout shorthands, plus `all` resets. It compares shared selector/condition contexts; separate alternatives
171
+ within one conditional or lookup are not assumed to apply together. Matching
172
+ atomic property/selector/condition keys are replaced during traced `cx`
173
+ composition before comparing the surviving declarations.
174
+
175
+ This is a bounded source review, not a CSS engine or a proof of precedence. It
176
+ does not execute helpers or import project modules, enumerate every external
177
+ class, or model arbitrary runtime mutation, component rendering, selectors or
178
+ overlapping media queries. Recursive calls, unsupported call/control-flow paths,
179
+ unresolved DOM targets and traversal limits produce bounded
180
+ `atomic-composition-limit` informational advisories where known atomic styles
181
+ reach an unresolved composition. Ordinary externally supplied className values
182
+ remain open inputs, not guaranteed safe styles. Depth, work and alternative
183
+ limits keep source inspection bounded; an unreported path or an empty warning
184
+ list does not establish visual correctness. Actual failed registered
185
+ browser/behavior checks remain blocking; potentially intentional source overlaps
186
+ remain warnings.
@@ -66,6 +66,13 @@ 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
70
+ `atomic-composition-review` / `atomic-composition-limit` advisory, read
71
+ [atomic style composition](references/atomic-styles.md). The same guide is served
72
+ as `ads://guides/atomic-styles`. It explains shorthand/logical conflicts and
73
+ matching-property fixes. Review warnings in the real `cx` composition and verify
74
+ computed styles across affected sizes/states; retain intentional product behavior.
75
+
69
76
  Controllers are UI behavior owners: private helpers stay with their component or
70
77
  pattern; reusable controllers use discovered `controllers/<Name>` units. Use the
71
78
  project's configured framework and declared dependencies, or plain TypeScript,
@@ -0,0 +1,186 @@
1
+ # Atomic style composition
2
+
3
+ Use this guide when creating or migrating component/pattern styles, changing
4
+ base/size/state combinations, or reviewing `atomic-composition-review` warnings.
5
+ It is also available as `ads://guides/atomic-styles` through ADS MCP.
6
+
7
+ ## Why valid tokens can still render incorrectly
8
+
9
+ Atomic Linaria extracts declarations into reusable classes. `cx` from
10
+ `@linaria/atomic` or `@linaria/core` replaces earlier atoms with the same property
11
+ and selector/condition key. It does not expand every CSS shorthand or resolve
12
+ every overlap between physical and logical properties.
13
+
14
+ For example, these declarations have different atomic keys:
15
+
16
+ ```tsx
17
+ const base = css`
18
+ padding: 0;
19
+ `;
20
+ const small = css`
21
+ padding-inline: var(--space-6);
22
+ `;
23
+
24
+ cx(base, small);
25
+ ```
26
+
27
+ Both classes survive. Both declarations can affect horizontal padding in a
28
+ horizontal writing mode. In the inspected Linaria implementation, `padding` and
29
+ `padding-inline` receive equal specificity. If a reset atom is emitted later,
30
+ it can override the intended size. Shared atom reuse and CSS splitting can make
31
+ this visible in a larger build even when an isolated view appears correct.
32
+ The order of class names in HTML does not decide equal-specificity rule order.
33
+ Valid tokens, successful extraction and a passing source check do not establish
34
+ the intended computed value.
35
+
36
+ See Linaria's [class merging implementation](https://github.com/callstack/linaria/blob/master/packages/core/src/cx.ts)
37
+ and [property priority implementation](https://github.com/callstack/linaria/blob/master/packages/atomic/src/processors/helpers/propertyPriority.ts).
38
+ Inspect the project's installed version when investigating its output.
39
+
40
+ ## Prefer matching properties across composed blocks
41
+
42
+ Express the reset and overrides using the same property vocabulary:
43
+
44
+ ```tsx
45
+ const base = css`
46
+ padding-block: 0;
47
+ padding-inline: 0;
48
+ `;
49
+ const small = css`
50
+ padding-inline: var(--space-6);
51
+ `;
52
+ const regular = css`
53
+ padding-block: var(--space-4);
54
+ padding-inline: var(--space-8);
55
+ `;
56
+
57
+ cx(base, compact ? small : regular);
58
+ ```
59
+
60
+ Now each selected size replaces the corresponding base atom through `cx`.
61
+ Review every size, including the default and icon-only variants. Changing only
62
+ one size can leave another size mixing shorthand and logical properties.
63
+ The names and tokens above are illustrative: use the project's real API and
64
+ declared tokens. Preserve its intended dimensions and supported writing modes.
65
+
66
+ The same reasoning applies to margin, inset, logical borders/corners, dimensions
67
+ and overflow. For example, prefer `margin-inline: 0` plus a size's
68
+ `margin-inline: var(...)` over combining `margin: 0` with that logical override.
69
+ Choose consistent physical properties when the product deliberately positions
70
+ against physical edges; logical properties are not mandatory.
71
+
72
+ An intentional state override may have a different selector or condition:
73
+
74
+ ```tsx
75
+ const treatment = css`
76
+ padding-inline: var(--space-6);
77
+ &:hover { padding-inline: var(--space-8); }
78
+ `;
79
+ ```
80
+
81
+ This is a distinct state, not two competing base atoms. Whether changing padding
82
+ on hover is desirable remains a product decision.
83
+
84
+ ## Follow helpers and forwarded classes
85
+
86
+ Composition can cross a helper or a component boundary. For example, in component
87
+ implementation source:
88
+
89
+ ```tsx
90
+ function baseClasses() { return base; }
91
+ function Primitive({ className, ...props }) {
92
+ return <button {...props} className={cx(baseClasses(), className)} />;
93
+ }
94
+ function CompactPrimitive(props) {
95
+ return <Primitive {...props} className={small} />;
96
+ }
97
+ ```
98
+
99
+ The base and small atoms can reach the same button. Inspect both owners when
100
+ correcting their property vocabulary. The wrapper's class does not style every
101
+ descendant: a class on a child or sibling element is a separate composition.
102
+ An imported stylesheet alone does not show that its classes co-apply.
103
+
104
+ Spread order matters. `<button className={base} {...props} />` can replace the
105
+ entire className; `<button {...props} className={cx(base, className)} />` composes
106
+ it explicitly. Keep the product's intended forwarding behavior when fixing an
107
+ overlap. Do not change the public API simply to make tracing easier.
108
+
109
+ Warnings include a bounded `composition` path through traced helpers and
110
+ components. A `target` identifies a statically reached DOM element. This
111
+ establishes source composition, not that a scenario mounted it or that its
112
+ computed result is wrong. `writingModeDependent: true` identifies overlaps that
113
+ change with direction or writing mode; evaluate those against supported modes.
114
+ Literal overlaps with provably equal values are omitted where the analyzer can
115
+ expand them safely. Token formulas, inheritance and runtime values still need
116
+ review. A margin shorthand and `margin-inline: auto` may agree horizontally but
117
+ disagree in vertical text, so horizontal equality alone is insufficient.
118
+
119
+ ## Respond to a warning
120
+
121
+ 1. Follow the warning's related file/line locations and inspect the actual `cx`
122
+ composition. Variant lookups may contribute several possible combinations.
123
+ 2. In a current built preview, inspect computed properties and the winning CSS
124
+ rules. Establish whether extraction order, specificity, writing mode or an
125
+ intentional override explains the result.
126
+ 3. For accidental overlap, align property names/granularity across the base and
127
+ affected variants. Use Linaria's `cx`, preserve tokens and fix the owning
128
+ component/pattern. Reordering class strings does not remove overlapping keys.
129
+ 4. Verify the affected sizes/states and supported directions in the normal app
130
+ and preview build. Add a registered rendered check when a specific geometry
131
+ or computed-style guarantee matters.
132
+
133
+ Increasing specificity, adding `!important`, copying styles into scenarios or
134
+ moving component styling into `base.css` can hide the symptom while retaining
135
+ the conflict. Prefer resolving the composition itself. If an overlap is
136
+ intentional, document why its precedence is stable and verify the resulting
137
+ behavior rather than changing product capabilities to silence a warning.
138
+
139
+ Use existing behavior contracts and `ads_verify` for important geometry. Register
140
+ a check beside its owner, link its real scenario and use the project's browser
141
+ profile. An assertion can inspect the actual control in the App frame:
142
+
143
+ ```ts
144
+ const frame = await openBehaviorScenario(page, "compact-spacing");
145
+ await expect(frame.getByRole("button", { name: "Compact" }))
146
+ .toHaveCSS("padding-inline-start", "8px");
147
+ ```
148
+
149
+ The name, check ID and expected value above are examples. Derive assertions from
150
+ the project's intended API and design, with relevant variants, open/hover/focus
151
+ states, themes and supported writing modes. Wait for observable readiness; an
152
+ event-stream connection can prevent `networkidle` from settling. A generic
153
+ overlap scan cannot decide which dimensions the product intended. A failed
154
+ registered geometry assertion is blocking through the existing verification
155
+ contract; an overlap warning remains a review signal.
156
+
157
+ ## What ADS checks
158
+
159
+ `atomic-composition-review` is a nonblocking warning, returned under `advisories`
160
+ with `severity: "warning"`. CLI checks still exit successfully when there are no
161
+ errors; MCP checks and mutations preserve the warning and its guidance URI.
162
+
163
+ The source review examines atomic Linaria templates and statically traceable
164
+ `cx` arguments, including aliases, local imports/re-exports, local helper returns,
165
+ arguments/defaults, nested composition, conditional expressions and variant-object
166
+ lookups. It follows explicit `className` forwarding through local function
167
+ components, props/rest spreads and imported React/Preact `memo`/`forwardRef`
168
+ wrappers to an intrinsic JSX element. It checks known overlaps involving box
169
+ spacing, inset, borders/corners, dimensions, overflow, backgrounds, typography,
170
+ motion and common layout shorthands, plus `all` resets. It compares shared selector/condition contexts; separate alternatives
171
+ within one conditional or lookup are not assumed to apply together. Matching
172
+ atomic property/selector/condition keys are replaced during traced `cx`
173
+ composition before comparing the surviving declarations.
174
+
175
+ This is a bounded source review, not a CSS engine or a proof of precedence. It
176
+ does not execute helpers or import project modules, enumerate every external
177
+ class, or model arbitrary runtime mutation, component rendering, selectors or
178
+ overlapping media queries. Recursive calls, unsupported call/control-flow paths,
179
+ unresolved DOM targets and traversal limits produce bounded
180
+ `atomic-composition-limit` informational advisories where known atomic styles
181
+ reach an unresolved composition. Ordinary externally supplied className values
182
+ remain open inputs, not guaranteed safe styles. Depth, work and alternative
183
+ limits keep source inspection bounded; an unreported path or an empty warning
184
+ list does not establish visual correctness. Actual failed registered
185
+ browser/behavior checks remain blocking; potentially intentional source overlaps
186
+ remain warnings.
package/docs/ADS.md CHANGED
@@ -367,6 +367,16 @@ Pointer capture without locally visible capture-loss cleanup produces a
367
367
  nonblocking advisory. Review delegated cleanup and browser behavior; neither a
368
368
  warning nor a handler's presence establishes lifecycle correctness.
369
369
 
370
+ Potential atomic CSS overlaps produce `atomic-composition-review` warnings with
371
+ related declarations and a guidance URI. They are nonblocking, including during
372
+ guarded mutations: valid CSS can intentionally overlap. Read
373
+ [atomic style composition](../skills/ads-designer/references/atomic-styles.md) for causes, matching-property fixes
374
+ and the source review's limits. Registered rendered checks can enforce a
375
+ project's intended computed geometry; token validity alone cannot establish it.
376
+ Bounded tracing follows local helpers and explicit `className` forwarding;
377
+ diagnostics distinguish a reached DOM target from informational analysis limits.
378
+ Neither a trace nor an absent warning establishes the intended rendered result.
379
+
370
380
  Document a new ownership exception with its guard/configuration change and
371
381
  tests. Passing static checks establishes only the policies and source formats
372
382
  they cover. Browser review and behavior tests still verify accessibility,
@@ -390,6 +400,13 @@ Validate accepted and rejected cases, configuration, and false-positive limits.
390
400
 
391
401
  ## Bootstrap and updates
392
402
 
403
+ The atomic composition guide lives in each skill's `references/atomic-styles.md`.
404
+ The maintained copy is in `skills/ads-designer/references/atomic-styles.md`;
405
+ MCP serves that packaged skill reference. `npm run sync:skill-references` copies
406
+ it to the other skills for standalone use; `npm run check:skill-references`
407
+ rejects drift during the tool build. Published packages include these references
408
+ under `dist/skills/`.
409
+
393
410
  Root [bootstrap-ds/](../bootstrap-ds/README.md) is the canonical empty scaffold.
394
411
  Its identical copy under `skills/ads-designer/assets/bootstrap-ds/` makes the
395
412
  skill self-contained. Run `npm run sync:skill-starter` after edits and
@@ -122,6 +122,15 @@ Linaria's [colocation and extraction model](https://github.com/callstack/linaria
122
122
  and [atomic composition model](https://github.com/callstack/linaria/blob/master/docs/ATOMIC_CSS.md)
123
123
  support this combination of local ownership and compiled styling.
124
124
 
125
+ Atomic merging matches property/selector/condition keys; it does not resolve
126
+ every shorthand/logical-property overlap. ADS reports detectable composition
127
+ risks as nonblocking warnings with guidance, while registered rendered checks
128
+ can enforce actual geometry. See the skill-local
129
+ [atomic style composition guide](../skills/ads-designer/references/atomic-styles.md).
130
+ Bounded source tracing follows local class helpers and explicit component
131
+ `className` forwarding to DOM targets. Separate elements remain separate;
132
+ unsupported paths are informational limits, not evidence of safe composition.
133
+
125
134
  Airbnb's 2022 [migration report](https://medium.com/airbnb-engineering/airbnbs-trip-to-linaria-dc169230bd12)
126
135
  provides practical evidence for this choice: performance was its leading
127
136
  criterion, with separate CSS caching and colocated authoring among the benefits.
package/docs/BEHAVIORS.md CHANGED
@@ -95,6 +95,19 @@ metadata string does not count. Dynamically passed behavior references produce a
95
95
  review advisory when a direct call cannot be established; verify those through
96
96
  registered execution checks rather than changing the API for the analyzer.
97
97
 
98
+ Callable exports may be functions, callable objects with attached methods, or
99
+ factory results. ADS uses their TypeScript call/construct signatures, including
100
+ the project's library declarations; it does not execute modules or maintain a
101
+ list of recognized factory names. The fast source guard resolves ambiguous public
102
+ values lazily and shares that type discovery within the check. Untyped `any`
103
+ values and objects containing methods do not establish a callable API.
104
+ An invalid `exercises` entry names the offending value and fails validation while
105
+ retaining independent render evidence for `covers`.
106
+ Calls to a callable's attached methods also exercise that public receiver,
107
+ including statically named member calls inside reachable event-handler closures.
108
+ Aliases, namespace access and re-exports retain the receiver identity. Reading a
109
+ method or defining an unused callback does not establish an invocation.
110
+
98
111
  Public APIs appear in `ads_catalog` with `apiKind: "ui"` or `"behavior"` and their
99
112
  scenario links. `ads_behaviors` joins contracts to demonstrations and evidence.
100
113
  A demonstrated API is not automatically a verified guarantee.