@symbo.ls/mcp 1.0.11 → 1.0.14
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.
- package/README.md +1 -0
- package/package.json +1 -1
- package/symbols_mcp/skills/AUDIT.md +148 -174
- package/symbols_mcp/skills/BRAND_IDENTITY.md +75 -0
- package/symbols_mcp/skills/COMPONENTS.md +151 -306
- package/symbols_mcp/skills/COOKBOOK.md +850 -0
- package/symbols_mcp/skills/DEFAULT_COMPONENTS.md +3856 -0
- package/symbols_mcp/skills/DEFAULT_LIBRARY.md +301 -0
- package/symbols_mcp/skills/DESIGN_CRITIQUE.md +70 -59
- package/symbols_mcp/skills/DESIGN_DIRECTION.md +109 -175
- package/symbols_mcp/skills/DESIGN_SYSTEM.md +473 -181
- package/symbols_mcp/skills/DESIGN_SYSTEM_ARCHITECT.md +65 -57
- package/symbols_mcp/skills/DESIGN_TO_CODE.md +83 -64
- package/symbols_mcp/skills/DESIGN_TREND.md +62 -50
- package/symbols_mcp/skills/FIGMA_MATCHING.md +69 -58
- package/symbols_mcp/skills/LEARNINGS.md +374 -0
- package/symbols_mcp/skills/MARKETING_ASSETS.md +71 -59
- package/symbols_mcp/skills/MIGRATION.md +158 -117
- package/symbols_mcp/skills/PATTERNS.md +101 -74
- package/symbols_mcp/skills/PRESENTATION.md +78 -0
- package/symbols_mcp/skills/PROJECT_STRUCTURE.md +114 -116
- package/symbols_mcp/skills/RULES.md +179 -148
- package/symbols_mcp/skills/RUNNING_APPS.md +476 -0
- package/symbols_mcp/skills/SEO-METADATA.md +33 -18
- package/symbols_mcp/skills/SNIPPETS.md +598 -0
- package/symbols_mcp/skills/SSR-BRENDER.md +99 -0
- package/symbols_mcp/skills/SYNTAX.md +356 -298
- package/symbols_mcp/skills/BRAND_INDENTITY.md +0 -69
- package/symbols_mcp/skills/THE_PRESENTATION.md +0 -69
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
# Migration
|
|
1
|
+
# Migration Rules: DOMQL v2 to v3 & Framework to Symbols
|
|
2
|
+
|
|
3
|
+
Apply these transformation rules when migrating code. Each rule is a BEFORE/AFTER pair.
|
|
2
4
|
|
|
3
5
|
---
|
|
4
6
|
|
|
5
|
-
## Part 1: DOMQL v2
|
|
7
|
+
## Part 1: DOMQL v2 to v3
|
|
8
|
+
|
|
9
|
+
### Rule Summary
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
| What changed | v2 (REMOVE) | v3 (USE INSTEAD) |
|
|
12
|
+
| ----------------------- | ----------------------------- | ----------------------------- |
|
|
13
|
+
| CSS props wrapper | `props: { padding: 'A' }` | `padding: 'A'` (at root) |
|
|
14
|
+
| Events wrapper | `on: { click: fn }` | `onClick: fn` (at root) |
|
|
15
|
+
| Inheritance | `extend: 'Component'` | `extends: 'Component'` |
|
|
16
|
+
| Child extend | `childExtend: 'Item'` | `childExtends: 'Item'` |
|
|
17
|
+
| Child element detection | any key including lowercase | PascalCase keys ONLY |
|
|
18
|
+
| Base components | `extends: 'Text'` / `'Box'` | Remove — implicit defaults |
|
|
8
19
|
|
|
9
|
-
|
|
10
|
-
| ------------------------- | ----------------------------- | ----------------------------- |
|
|
11
|
-
| CSS props wrapper | `props: { padding: 'A' }` | `padding: 'A'` (at root) |
|
|
12
|
-
| Events wrapper | `on: { click: fn }` | `onClick: fn` (at root) |
|
|
13
|
-
| Inheritance | `extend: 'Component'` | `extends: 'Component'` |
|
|
14
|
-
| Child extend | `childExtend: 'Item'` | `childExtends: 'Item'` |
|
|
15
|
-
| Child element detection | any key including lowercase | PascalCase keys ONLY |
|
|
20
|
+
### Rule 1: Flatten `props` and `on`
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
Move all `props` entries to root. Remove `on` wrapper; prefix each event with `on` + CapitalizedEventName. Apply at root AND all nested elements.
|
|
18
23
|
|
|
24
|
+
BEFORE:
|
|
19
25
|
```js
|
|
20
|
-
// v2
|
|
21
26
|
{
|
|
22
27
|
props: { position: 'absolute', gap: 'A' },
|
|
23
28
|
on: {
|
|
@@ -26,8 +31,10 @@
|
|
|
26
31
|
wheel: (e, t) => {},
|
|
27
32
|
},
|
|
28
33
|
}
|
|
34
|
+
```
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
AFTER:
|
|
37
|
+
```js
|
|
31
38
|
{
|
|
32
39
|
position: 'absolute',
|
|
33
40
|
gap: 'A',
|
|
@@ -37,38 +44,39 @@
|
|
|
37
44
|
}
|
|
38
45
|
```
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
- Move all `props` entries directly to the component object root
|
|
42
|
-
- Remove the `on` wrapper; prefix each event with `on` + `CapitalizedEventName`
|
|
43
|
-
- Applies to root and all nested elements
|
|
44
|
-
|
|
45
|
-
### Rename properties
|
|
47
|
+
### Rule 2: Rename `extend` to `extends`, `childExtend` to `childExtends`
|
|
46
48
|
|
|
49
|
+
BEFORE:
|
|
47
50
|
```js
|
|
48
|
-
// v2
|
|
49
51
|
{ extend: SomeComponent, childExtend: AnotherComponent }
|
|
52
|
+
```
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
AFTER:
|
|
55
|
+
```js
|
|
52
56
|
{ extends: SomeComponent, childExtends: AnotherComponent }
|
|
53
57
|
```
|
|
54
58
|
|
|
55
|
-
### Replace `$stateCollection` with `children` + `childrenAs: 'state'`
|
|
59
|
+
### Rule 3: Replace `$stateCollection` with `children` + `childrenAs: 'state'`
|
|
56
60
|
|
|
61
|
+
BEFORE:
|
|
57
62
|
```js
|
|
58
|
-
// v2
|
|
59
63
|
{
|
|
60
64
|
childExtend: 'TeamItem',
|
|
61
65
|
$stateCollection: (el, s) => s.data
|
|
62
66
|
}
|
|
67
|
+
```
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
AFTER (Option A -- explicit):
|
|
70
|
+
```js
|
|
65
71
|
{
|
|
66
72
|
childExtends: 'TeamItem',
|
|
67
73
|
childrenAs: 'state',
|
|
68
74
|
children: (el, s) => s.data
|
|
69
75
|
}
|
|
76
|
+
```
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
AFTER (Option B -- preferred for nested state):
|
|
79
|
+
```js
|
|
72
80
|
{
|
|
73
81
|
state: 'data',
|
|
74
82
|
childExtends: 'TeamItem',
|
|
@@ -76,10 +84,9 @@ Rules:
|
|
|
76
84
|
}
|
|
77
85
|
```
|
|
78
86
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
Components used with `childExtends` that read individual item state (e.g. `({ state }) => state.title`) need `state: true` at their root so each child receives its own state from the parent's children array:
|
|
87
|
+
**`state: true` requirement for child components:** Components used with `childExtends` that read individual item state need `state: true` at their root so each child receives its own state from the parent's children array.
|
|
82
88
|
|
|
89
|
+
BEFORE (parent + child):
|
|
83
90
|
```js
|
|
84
91
|
// Parent container
|
|
85
92
|
export const TeamList = {
|
|
@@ -88,7 +95,7 @@ export const TeamList = {
|
|
|
88
95
|
children: ({ state }) => state
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
// Child component
|
|
98
|
+
// Child component -- state: true is REQUIRED
|
|
92
99
|
export const TeamItem = {
|
|
93
100
|
state: true,
|
|
94
101
|
Title: { text: ({ state }) => state.name },
|
|
@@ -96,102 +103,111 @@ export const TeamItem = {
|
|
|
96
103
|
}
|
|
97
104
|
```
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
**WRONG**: `children: ({ state }) => state.data` does NOT properly pass individual state to child components — all children receive the parent's full state instead of their own item.
|
|
102
|
-
|
|
103
|
-
**CORRECT**: Use `state: 'data'` on the container first, then `children: ({ state }) => state`:
|
|
106
|
+
**CRITICAL PITFALL -- `children: ({ state }) => state.data`:**
|
|
104
107
|
|
|
108
|
+
WRONG -- children don't get individual state:
|
|
105
109
|
```js
|
|
106
|
-
// ❌ WRONG — children don't get individual state
|
|
107
110
|
{ children: ({ state }) => state.data, childExtends: 'Item' }
|
|
111
|
+
```
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
CORRECT -- `state: 'data'` narrows scope, children get individual items:
|
|
114
|
+
```js
|
|
110
115
|
{ state: 'data', children: ({ state }) => state, childExtends: 'Item' }
|
|
111
116
|
```
|
|
112
117
|
|
|
113
|
-
### Replace `$propsCollection` with `children`
|
|
118
|
+
### Rule 4: Replace `$propsCollection` with `children`
|
|
119
|
+
|
|
120
|
+
`$propsCollection` is fully removed in v3. Replace 1:1 with `children`.
|
|
114
121
|
|
|
122
|
+
BEFORE:
|
|
115
123
|
```js
|
|
116
|
-
// v2
|
|
117
124
|
{
|
|
118
125
|
childExtend: 'Paragraph',
|
|
119
126
|
$propsCollection: ({ state }) => state.parse()
|
|
120
127
|
}
|
|
128
|
+
```
|
|
121
129
|
|
|
122
|
-
|
|
130
|
+
AFTER:
|
|
131
|
+
```js
|
|
123
132
|
{
|
|
124
133
|
childExtends: 'Paragraph',
|
|
125
134
|
children: ({ state }) => state.parse()
|
|
126
135
|
}
|
|
127
136
|
```
|
|
128
137
|
|
|
129
|
-
|
|
138
|
+
Also applies to array data:
|
|
130
139
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
$propsCollection: ({ state }) => state
|
|
140
|
+
BEFORE: `$propsCollection: ({ state }) => state`
|
|
141
|
+
AFTER: `children: ({ state }) => state`
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
children: ({ state }) => state
|
|
137
|
-
```
|
|
143
|
+
### Rule 5: Replace `props: (fn)` function with individual prop functions
|
|
138
144
|
|
|
139
|
-
|
|
145
|
+
Dynamic props functions are REMOVED in v3. Split into per-property functions.
|
|
140
146
|
|
|
147
|
+
BEFORE:
|
|
141
148
|
```js
|
|
142
|
-
// v2 — dynamic props function (REMOVED in v3)
|
|
143
149
|
{
|
|
144
150
|
props: ({ state }) => ({
|
|
145
151
|
color: state.active ? 'red' : 'blue',
|
|
146
152
|
opacity: state.loading ? 0.5 : 1
|
|
147
153
|
})
|
|
148
154
|
}
|
|
155
|
+
```
|
|
149
156
|
|
|
150
|
-
|
|
157
|
+
AFTER:
|
|
158
|
+
```js
|
|
151
159
|
{
|
|
152
160
|
color: ({ state }) => state.active ? 'red' : 'blue',
|
|
153
161
|
opacity: ({ state }) => state.loading ? 0.5 : 1
|
|
154
162
|
}
|
|
155
163
|
```
|
|
156
164
|
|
|
157
|
-
###
|
|
165
|
+
### Rule 6: PascalCase-only child elements
|
|
158
166
|
|
|
167
|
+
In v3, only PascalCase keys create child elements. Lowercase keys are treated as CSS properties.
|
|
168
|
+
|
|
169
|
+
BEFORE (v2):
|
|
159
170
|
```js
|
|
160
|
-
// v2 — lowercase keys could create elements
|
|
161
171
|
{ div: {} } // creates <div>
|
|
172
|
+
```
|
|
162
173
|
|
|
163
|
-
|
|
174
|
+
AFTER (v3):
|
|
175
|
+
```js
|
|
164
176
|
{ div: {} } // treated as a plain prop, NOT rendered
|
|
165
177
|
{ Div: {} } // creates a child element (equivalent to { extends: 'Div' })
|
|
166
178
|
```
|
|
167
179
|
|
|
168
|
-
### Replace array spread
|
|
180
|
+
### Rule 7: Replace array spread with `children` array
|
|
169
181
|
|
|
182
|
+
Array spread creates numeric keys (`0`, `1`, `2`...) which v3 treats as CSS properties. Always use `children` array.
|
|
183
|
+
|
|
184
|
+
BEFORE:
|
|
170
185
|
```js
|
|
171
|
-
// v2 — numeric keys from spread are lowercase, treated as CSS in v3
|
|
172
186
|
{
|
|
173
187
|
childExtend: 'NavLink',
|
|
174
188
|
...[{ text: 'About us' }, { text: 'Hiring' }]
|
|
175
189
|
}
|
|
190
|
+
```
|
|
176
191
|
|
|
177
|
-
|
|
192
|
+
AFTER:
|
|
193
|
+
```js
|
|
178
194
|
{
|
|
179
195
|
childExtends: 'NavLink',
|
|
180
196
|
children: [{ text: 'About us' }, { text: 'Hiring' }]
|
|
181
197
|
}
|
|
182
198
|
```
|
|
183
199
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
### Picture `src` must go on Img child
|
|
200
|
+
### Rule 8: Picture `src` must go on Img child
|
|
187
201
|
|
|
188
202
|
The HTML `<picture>` tag does NOT support `src` as an attribute. In v3, lowercase props move to `element.props`, so `element.parent.src` returns `undefined`.
|
|
189
203
|
|
|
204
|
+
WRONG:
|
|
190
205
|
```js
|
|
191
|
-
// ❌ WRONG — src on Picture is silently ignored
|
|
192
206
|
Picture: { src: '/files/photo.jpg', width: '100%' }
|
|
207
|
+
```
|
|
193
208
|
|
|
194
|
-
|
|
209
|
+
CORRECT:
|
|
210
|
+
```js
|
|
195
211
|
Picture: {
|
|
196
212
|
Img: { src: '/files/photo.jpg' },
|
|
197
213
|
width: '100%',
|
|
@@ -201,37 +217,42 @@ Picture: {
|
|
|
201
217
|
|
|
202
218
|
For theme-aware sources, use `@dark`/`@light` with `srcset` on Picture, but always put the default `src` on the Img child.
|
|
203
219
|
|
|
204
|
-
### `<map>` tag auto-detection
|
|
220
|
+
### Rule 9: `<map>` tag auto-detection
|
|
205
221
|
|
|
206
222
|
Component keys named `Map` auto-detect as the HTML `<map>` tag (for image maps), which defaults to `display: inline` and has height 0. If using `Map` as a component name for geographic maps or similar, add `tag: 'div'`:
|
|
207
223
|
|
|
208
224
|
```js
|
|
209
225
|
export const Map = {
|
|
210
|
-
|
|
226
|
+
flow: 'y',
|
|
211
227
|
tag: 'div', // prevents <map> auto-detection
|
|
212
228
|
// ...
|
|
213
229
|
}
|
|
214
230
|
```
|
|
215
231
|
|
|
216
|
-
### Non-existent base components
|
|
232
|
+
### Rule 10: Non-existent base components
|
|
217
233
|
|
|
218
234
|
These v2 component names don't exist in v3 uikit:
|
|
219
|
-
- `extends: 'Page'` → use `extends: 'Flex', flexFlow: 'column'`
|
|
220
|
-
- `extends: 'Overflow'` → use `extends: 'Flex'`
|
|
221
235
|
|
|
222
|
-
|
|
236
|
+
| v2 (REMOVE) | v3 (USE INSTEAD) |
|
|
237
|
+
| ---------------------- | ----------------------------------------- |
|
|
238
|
+
| `extends: 'Page'` | `flow: 'column'` |
|
|
239
|
+
| `extends: 'Overflow'` | `flow: 'x'` |
|
|
223
240
|
|
|
224
|
-
|
|
225
|
-
|
|
241
|
+
### Rule 11: `state: true` vs `state: 'fieldName'` for children
|
|
242
|
+
|
|
243
|
+
| Context | Use | Purpose |
|
|
244
|
+
| ---------------------------------- | ---------------- | --------------------------------------------------------- |
|
|
245
|
+
| `childExtends`-created children | `state: true` | Maps individual array items as each child's state |
|
|
246
|
+
| Direct PascalCase children | `state: 'field'` | Picks a specific field from parent state |
|
|
226
247
|
|
|
227
248
|
```js
|
|
228
|
-
// childExtends children
|
|
249
|
+
// childExtends children -- use state: true on the child component
|
|
229
250
|
export const ListItem = {
|
|
230
251
|
state: true,
|
|
231
252
|
Title: { text: ({ state }) => state.name }
|
|
232
253
|
}
|
|
233
254
|
|
|
234
|
-
// Direct PascalCase child
|
|
255
|
+
// Direct PascalCase child -- use state: 'fieldName'
|
|
235
256
|
Description: {
|
|
236
257
|
state: 'description',
|
|
237
258
|
childExtends: 'Paragraph',
|
|
@@ -239,10 +260,28 @@ Description: {
|
|
|
239
260
|
}
|
|
240
261
|
```
|
|
241
262
|
|
|
242
|
-
###
|
|
263
|
+
### Rule 12: Remove `extends: 'Text'` and `extends: 'Box'`
|
|
264
|
+
|
|
265
|
+
`Text` and `Box` are built-in implicit defaults. Extending them causes unnecessary merge at runtime.
|
|
243
266
|
|
|
267
|
+
BEFORE:
|
|
268
|
+
```js
|
|
269
|
+
Tag: { extends: 'Text', text: 'NEW', padding: 'X A' }
|
|
270
|
+
Card: { extends: 'Box', padding: 'B', background: 'white' }
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
AFTER:
|
|
274
|
+
```js
|
|
275
|
+
Tag: { tag: 'span', text: 'NEW', padding: 'X A' }
|
|
276
|
+
Card: { tag: 'div', padding: 'B', background: 'white' }
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Use semantic or functional components instead (`Flex`, `Link`, `Button`, `Header`, `Section`, etc.).
|
|
280
|
+
|
|
281
|
+
### Full v2 to v3 transformation example
|
|
282
|
+
|
|
283
|
+
BEFORE:
|
|
244
284
|
```js
|
|
245
|
-
// v2
|
|
246
285
|
{
|
|
247
286
|
extend: 'Flex',
|
|
248
287
|
childExtend: 'ListItem',
|
|
@@ -262,10 +301,12 @@ Description: {
|
|
|
262
301
|
},
|
|
263
302
|
},
|
|
264
303
|
}
|
|
304
|
+
```
|
|
265
305
|
|
|
266
|
-
|
|
306
|
+
AFTER:
|
|
307
|
+
```js
|
|
267
308
|
{
|
|
268
|
-
|
|
309
|
+
flow: 'x',
|
|
269
310
|
childExtends: 'ListItem',
|
|
270
311
|
position: 'absolute',
|
|
271
312
|
attr: { 'gs-w': 1, 'gs-h': 1 },
|
|
@@ -283,13 +324,13 @@ Description: {
|
|
|
283
324
|
|
|
284
325
|
---
|
|
285
326
|
|
|
286
|
-
## Part 2: React / Angular / Vue
|
|
327
|
+
## Part 2: React / Angular / Vue to Symbols
|
|
287
328
|
|
|
288
|
-
###
|
|
329
|
+
### React to Symbols
|
|
289
330
|
|
|
290
331
|
| React Pattern | Symbols Equivalent |
|
|
291
332
|
| -------------------------------------- | ------------------------------------------------------------------------- |
|
|
292
|
-
| `function Component()` / `class` | `export const Component = {
|
|
333
|
+
| `function Component()` / `class` | `export const Component = { flow: 'y', ... }` |
|
|
293
334
|
| `import Component from './Component'` | Reference by key: `{ Component: {} }` |
|
|
294
335
|
| `useState(val)` | `state: { key: val }` + `s.update({ key: newVal })` |
|
|
295
336
|
| `useEffect(() => {}, [])` | `onRender: (el, s) => {}` |
|
|
@@ -310,7 +351,7 @@ Description: {
|
|
|
310
351
|
| `<form onSubmit>` | `tag: 'form', onSubmit: (ev, el, s) => { ev.preventDefault(); ... }` |
|
|
311
352
|
| `fetch()` in components | `functions/fetch.js` + `el.call('fetch', method, path, data)` |
|
|
312
353
|
|
|
313
|
-
###
|
|
354
|
+
### Angular to Symbols
|
|
314
355
|
|
|
315
356
|
| Angular Pattern | Symbols Equivalent |
|
|
316
357
|
| ---------------------------------- | ---------------------------------------------------------------------- |
|
|
@@ -334,7 +375,7 @@ Description: {
|
|
|
334
375
|
| SCSS / component styles | Flatten to props with design tokens |
|
|
335
376
|
| Reactive Forms | `tag: 'form'`, `Input` children with `name`, `onSubmit` handler |
|
|
336
377
|
|
|
337
|
-
###
|
|
378
|
+
### Vue to Symbols
|
|
338
379
|
|
|
339
380
|
| Vue Pattern | Symbols Equivalent |
|
|
340
381
|
| --------------------------------- | --------------------------------------------------------------------------------- |
|
|
@@ -361,7 +402,7 @@ Description: {
|
|
|
361
402
|
|
|
362
403
|
---
|
|
363
404
|
|
|
364
|
-
## Part 3: CSS
|
|
405
|
+
## Part 3: CSS to Design Tokens
|
|
365
406
|
|
|
366
407
|
| CSS | Symbols |
|
|
367
408
|
| ----------------------------------------------------- | -------------------------------------------- |
|
|
@@ -373,7 +414,7 @@ Description: {
|
|
|
373
414
|
| `width: 42px; height: 42px` | `boxSize: 'C'` |
|
|
374
415
|
| `display: flex; flex-direction: column` | `flow: 'y'` |
|
|
375
416
|
| `display: flex; flex-direction: row` | `flow: 'x'` |
|
|
376
|
-
| `align-items: center; justify-content: center` | `
|
|
417
|
+
| `align-items: center; justify-content: center` | `align: 'center center'` |
|
|
377
418
|
| `display: grid; grid-template-columns: repeat(3,1fr)` | `extends: 'Grid', columns: 'repeat(3, 1fr)'` |
|
|
378
419
|
| `font-size: 20px` | `fontSize: 'A1'` |
|
|
379
420
|
| `font-weight: 500` | `fontWeight: '500'` |
|
|
@@ -411,9 +452,8 @@ Use this as the base template for every new component:
|
|
|
411
452
|
```js
|
|
412
453
|
// components/ComponentName.js
|
|
413
454
|
export const ComponentName = {
|
|
414
|
-
extends: 'Flex',
|
|
415
|
-
|
|
416
455
|
// Props flattened at root (design tokens)
|
|
456
|
+
flow: 'y',
|
|
417
457
|
padding: 'A B',
|
|
418
458
|
background: 'surface',
|
|
419
459
|
borderRadius: 'B',
|
|
@@ -434,7 +474,7 @@ export const ComponentName = {
|
|
|
434
474
|
'@mobileL': { padding: 'A' },
|
|
435
475
|
'@tabletS': { padding: 'B' },
|
|
436
476
|
|
|
437
|
-
// Children
|
|
477
|
+
// Children -- PascalCase keys, no imports
|
|
438
478
|
Header: {},
|
|
439
479
|
Content: {
|
|
440
480
|
Article: { text: 'Hello' },
|
|
@@ -447,15 +487,16 @@ export const ComponentName = {
|
|
|
447
487
|
|
|
448
488
|
## Part 5: State Management Migration
|
|
449
489
|
|
|
450
|
-
| Framework pattern
|
|
451
|
-
|
|
|
452
|
-
| Global store (Redux, Pinia, NgRx)
|
|
453
|
-
| Local component state
|
|
454
|
-
| Derived/computed state
|
|
455
|
-
| Async data fetch
|
|
456
|
-
| State persistence
|
|
490
|
+
| Framework pattern | Symbols equivalent |
|
|
491
|
+
| --------------------------------------- | ----------------------------------------------------------------------------- |
|
|
492
|
+
| Global store (Redux, Pinia, NgRx) | `state/index.js` with initial flat state. Access via `s.root` in any component |
|
|
493
|
+
| Local component state | `state: { key: val }` on the component |
|
|
494
|
+
| Derived/computed state | Dynamic prop function: `text: (el, s) => derived(s)` |
|
|
495
|
+
| Async data fetch | `onRender: async (el, s) => { ... s.update({data}) }` |
|
|
496
|
+
| State persistence | Functions that read/write to localStorage/cookie |
|
|
497
|
+
|
|
498
|
+
Async state pattern:
|
|
457
499
|
|
|
458
|
-
Example async state pattern:
|
|
459
500
|
```js
|
|
460
501
|
export const DataView = {
|
|
461
502
|
state: { data: null, loading: true, error: null },
|
|
@@ -477,43 +518,43 @@ export const DataView = {
|
|
|
477
518
|
|
|
478
519
|
### Color tokens: space-separated to dot-notation
|
|
479
520
|
|
|
480
|
-
|
|
|
481
|
-
|
|
482
|
-
| `'white .1'`
|
|
483
|
-
| `'gray 0.85'`
|
|
484
|
-
| `'gray .92 +8'`
|
|
485
|
-
| `'gray 1 +16'`
|
|
486
|
-
| `'gray 1 -68'`
|
|
487
|
-
| `'gray 1 90'`
|
|
488
|
-
| `'white 1 -78'`
|
|
521
|
+
| BEFORE | AFTER | Notes |
|
|
522
|
+
| ----------------- | ---------------- | ----------------------------- |
|
|
523
|
+
| `'white .1'` | `'white.1'` | Opacity 0.1 |
|
|
524
|
+
| `'gray 0.85'` | `'gray.85'` | Opacity 0.85 |
|
|
525
|
+
| `'gray .92 +8'` | `'gray.92+8'` | Opacity + relative tone |
|
|
526
|
+
| `'gray 1 +16'` | `'gray+16'` | Alpha 1 = default, omit |
|
|
527
|
+
| `'gray 1 -68'` | `'gray-68'` | Relative tone |
|
|
528
|
+
| `'gray 1 90'` | `'gray=90'` | Absolute lightness (=prefix) |
|
|
529
|
+
| `'white 1 -78'` | `'white-78'` | Tone only |
|
|
489
530
|
|
|
490
531
|
### border: comma-separated to space-separated (CSS order)
|
|
491
532
|
|
|
492
|
-
|
|
|
493
|
-
|
|
494
|
-
| `'solid, gray, 1px'`
|
|
495
|
-
| `'gray6 .1, solid, 1px'`
|
|
496
|
-
| `'solid, mediumGrey'`
|
|
497
|
-
| `'1px, solid'`
|
|
533
|
+
| BEFORE | AFTER |
|
|
534
|
+
| --------------------------- | ----------------------- |
|
|
535
|
+
| `'solid, gray, 1px'` | `'1px solid gray'` |
|
|
536
|
+
| `'gray6 .1, solid, 1px'` | `'1px solid gray6.1'` |
|
|
537
|
+
| `'solid, mediumGrey'` | `'solid mediumGrey'` |
|
|
538
|
+
| `'1px, solid'` | `'1px solid'` |
|
|
498
539
|
|
|
499
540
|
### boxShadow: commas to spaces within shadow, pipe to comma between shadows
|
|
500
541
|
|
|
501
|
-
|
|
|
502
|
-
|
|
503
|
-
| `'white .1, 0, A, C, C'`
|
|
504
|
-
| `'black .10, 0px, 2px, 8px, 0px'`
|
|
505
|
-
| `'a, b \| c, d'`
|
|
542
|
+
| BEFORE | AFTER |
|
|
543
|
+
| ----------------------------------- | --------------------------- |
|
|
544
|
+
| `'white .1, 0, A, C, C'` | `'white.1 0 A C C'` |
|
|
545
|
+
| `'black .10, 0px, 2px, 8px, 0px'` | `'black.1 0px 2px 8px 0px'` |
|
|
546
|
+
| `'a, b \| c, d'` | `'a b, c d'` |
|
|
506
547
|
|
|
507
548
|
### textStroke/textShadow: comma-separated to space-separated
|
|
508
549
|
|
|
509
|
-
|
|
|
510
|
-
|
|
511
|
-
| `'1px, gray6'`
|
|
512
|
-
| `'gray1, 6px, 6px'`
|
|
550
|
+
| BEFORE | AFTER |
|
|
551
|
+
| --------------------- | ------------------ |
|
|
552
|
+
| `'1px, gray6'` | `'1px gray6'` |
|
|
553
|
+
| `'gray1, 6px, 6px'` | `'gray1 6px 6px'` |
|
|
513
554
|
|
|
514
555
|
### CSS fallback
|
|
515
556
|
|
|
516
|
-
Raw CSS values
|
|
557
|
+
Raw CSS values pass through unchanged:
|
|
517
558
|
```js
|
|
518
559
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)' // passes through as-is
|
|
519
560
|
border: '1px solid #333' // passes through as-is
|