@champpaba/claude-agent-kit 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CHANGELOG.md +67 -0
- package/.claude/CLAUDE.md +2 -1
- package/.claude/commands/cdev.md +276 -239
- package/.claude/commands/csetup.md +985 -1062
- package/.claude/commands/cstatus.md +62 -53
- package/.claude/commands/cview.md +49 -50
- package/.claude/commands/designsetup.md +958 -1910
- package/.claude/commands/extract.md +480 -743
- package/.claude/commands/pageplan.md +155 -153
- package/.claude/commands/pstatus.md +322 -254
- package/package.json +1 -1
|
@@ -45,47 +45,60 @@ Generate design system files:
|
|
|
45
45
|
|
|
46
46
|
## STEP 0: Discovery & Validation
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
// 1. Find extracted sites from design-system/extracted/*/data.yaml
|
|
50
|
-
const extractedDirs = glob('design-system/extracted/*/data.yaml');
|
|
48
|
+
### STEP 0.1: Find Extracted Site Data
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
1. Search for extracted site data:
|
|
51
|
+
```
|
|
52
|
+
Glob: design-system/extracted/*/data.yaml
|
|
53
|
+
```
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
**If no files found:**
|
|
56
|
+
```
|
|
57
|
+
❌ No extracted data found
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
Please extract at least 1 site first:
|
|
60
|
+
/extract https://motherduck.com
|
|
61
|
+
/extract https://linear.app
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const siteName = path.basename(path.dirname(file)); // Get folder name
|
|
68
|
-
extractedData[siteName] = YAML.parse(Read(file));
|
|
69
|
-
}
|
|
63
|
+
Then run: /designsetup @prd.md @project.md
|
|
64
|
+
```
|
|
65
|
+
→ STOP here, do not continue
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
**If files found:**
|
|
68
|
+
```
|
|
69
|
+
✅ Found extracted sites: [list site names]
|
|
70
|
+
```
|
|
71
|
+
→ Continue to STEP 0.2
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
for (const arg of contextArgs) {
|
|
77
|
-
const filePath = arg.substring(1); // Remove @
|
|
73
|
+
### STEP 0.2: Load Extracted Site Data
|
|
78
74
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
For each extracted site found:
|
|
76
|
+
1. Extract the site name from the path (the folder name between `extracted/` and `/data.yaml`)
|
|
77
|
+
2. Read the data.yaml file
|
|
78
|
+
3. Parse the YAML content
|
|
79
|
+
4. Store in memory for later use (map site name to data)
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
→ Continue to STEP 0.3
|
|
82
|
+
|
|
83
|
+
### STEP 0.3: Load Context Files (Optional)
|
|
84
|
+
|
|
85
|
+
1. Check if user provided context files (arguments starting with `@`)
|
|
86
|
+
|
|
87
|
+
**If no context files provided:**
|
|
88
|
+
- Set contexts as empty
|
|
89
|
+
- Will use interactive mode later
|
|
90
|
+
→ Continue to STEP 0.4
|
|
91
|
+
|
|
92
|
+
**If context files provided:**
|
|
93
|
+
For each context file argument:
|
|
94
|
+
1. Remove the `@` prefix to get the file path
|
|
95
|
+
2. Check if file exists:
|
|
96
|
+
- **If not found:** Warn user and skip this file
|
|
97
|
+
- **If found:** Read the file content and store with filename as key
|
|
98
|
+
|
|
99
|
+
→ Continue to STEP 0.4
|
|
100
|
+
|
|
101
|
+
### STEP 0.4: Report Discovery Results
|
|
89
102
|
|
|
90
103
|
**Report:**
|
|
91
104
|
```
|
|
@@ -110,19 +123,24 @@ ${Object.keys(contexts).length > 0 ? Object.keys(contexts).map(c => ` - ${c}`)
|
|
|
110
123
|
|
|
111
124
|
## STEP 1: Context Analysis
|
|
112
125
|
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
### STEP 1.1: Check for Context Files
|
|
127
|
+
|
|
128
|
+
**If context files were loaded in STEP 0.3:**
|
|
129
|
+
→ Continue to STEP 1.2 (AI Analysis)
|
|
115
130
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
**If no context files:**
|
|
132
|
+
→ Skip to STEP 1.3 (Interactive Questions)
|
|
133
|
+
|
|
134
|
+
### STEP 1.2: AI Analysis of Context Files
|
|
135
|
+
|
|
136
|
+
1. Ask Claude to analyze the context files and identify project characteristics
|
|
137
|
+
|
|
138
|
+
**Analysis Prompt:**
|
|
139
|
+
```
|
|
119
140
|
You are analyzing project context to recommend design directions.
|
|
120
141
|
|
|
121
142
|
Context Files:
|
|
122
|
-
|
|
123
|
-
## ${name}
|
|
124
|
-
${content.substring(0, 2000)} // First 2000 chars
|
|
125
|
-
`).join('\n')}
|
|
143
|
+
[Include each context file name and first 2000 characters of content]
|
|
126
144
|
|
|
127
145
|
Task: Identify project characteristics and return JSON.
|
|
128
146
|
|
|
@@ -146,69 +164,56 @@ Return JSON:
|
|
|
146
164
|
}
|
|
147
165
|
|
|
148
166
|
If context is insufficient or unclear, set "has_context": false.
|
|
149
|
-
|
|
167
|
+
```
|
|
150
168
|
|
|
151
|
-
|
|
152
|
-
prompt: analysisPrompt,
|
|
153
|
-
response_format: 'json'
|
|
154
|
-
});
|
|
169
|
+
2. Parse the JSON response from Claude
|
|
155
170
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
171
|
+
**If has_context is true:**
|
|
172
|
+
→ Skip to STEP 1.4 (Report)
|
|
159
173
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
product_type: userInput.answers["Product Type"],
|
|
204
|
-
target_audience: {
|
|
205
|
-
demographics: userInput.answers["Audience"],
|
|
206
|
-
tech_savvy: userInput.answers["Audience"].includes("Gen Z") || userInput.answers["Audience"].includes("Developers") ? "high" : "medium"
|
|
207
|
-
},
|
|
208
|
-
brand_personality: userInput.answers["Brand"].split(',').map(s => s.trim().toLowerCase())
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
```
|
|
174
|
+
**If has_context is false:**
|
|
175
|
+
→ Continue to STEP 1.3 (Interactive Questions)
|
|
176
|
+
|
|
177
|
+
### STEP 1.3: Interactive Questions (Fallback)
|
|
178
|
+
|
|
179
|
+
Ask user to answer these questions:
|
|
180
|
+
|
|
181
|
+
**Question 1: Product Type**
|
|
182
|
+
- Header: "Product Type"
|
|
183
|
+
- Single selection
|
|
184
|
+
- Options:
|
|
185
|
+
- "SaaS Dashboard" - Business software, data tools, analytics
|
|
186
|
+
- "E-commerce" - Online store, marketplace, shopping
|
|
187
|
+
- "Marketing Site" - Landing pages, content, blog
|
|
188
|
+
- "Internal Tool" - Admin panels, workflows, dashboards
|
|
189
|
+
|
|
190
|
+
**Question 2: Target Audience**
|
|
191
|
+
- Header: "Audience"
|
|
192
|
+
- Single selection
|
|
193
|
+
- Options:
|
|
194
|
+
- "Gen Z (18-25)" - Young, tech-savvy, bold preferences
|
|
195
|
+
- "Millennials (26-40)" - Professional, value-driven, modern
|
|
196
|
+
- "Enterprise (40+)" - Conservative, trust-focused, established
|
|
197
|
+
- "Developers" - Technical, efficiency-focused, minimal
|
|
198
|
+
|
|
199
|
+
**Question 3: Brand Personality**
|
|
200
|
+
- Header: "Brand"
|
|
201
|
+
- Multiple selection allowed
|
|
202
|
+
- Options:
|
|
203
|
+
- "Bold" - Stand out, memorable, confident, different
|
|
204
|
+
- "Professional" - Trustworthy, credible, serious, polished
|
|
205
|
+
- "Playful" - Fun, friendly, approachable, warm
|
|
206
|
+
- "Minimal" - Clean, simple, understated, elegant
|
|
207
|
+
|
|
208
|
+
Build context analysis from user answers:
|
|
209
|
+
- product_type: from Question 1
|
|
210
|
+
- target_audience.demographics: from Question 2
|
|
211
|
+
- target_audience.tech_savvy: "high" if Gen Z or Developers selected, otherwise "medium"
|
|
212
|
+
- brand_personality: list from Question 3 (converted to lowercase)
|
|
213
|
+
|
|
214
|
+
→ Continue to STEP 1.4
|
|
215
|
+
|
|
216
|
+
### STEP 1.4: Report Context Analysis
|
|
212
217
|
|
|
213
218
|
**Report:**
|
|
214
219
|
```
|
|
@@ -229,231 +234,197 @@ if (!contextAnalysis.has_context) {
|
|
|
229
234
|
|
|
230
235
|
> **Key Change:** Interactive loop until user accepts 100%
|
|
231
236
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
let selectedStyle = null;
|
|
237
|
-
let selectedAnimations = [];
|
|
238
|
-
let selectedTheme = null;
|
|
237
|
+
**Loop Configuration:**
|
|
238
|
+
- Maximum rounds: 3
|
|
239
|
+
- Current round: starts at 1
|
|
240
|
+
- User must accept to exit loop
|
|
239
241
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
### STEP 2.1: Start New Round
|
|
243
|
+
|
|
244
|
+
Display round header:
|
|
245
|
+
```
|
|
242
246
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
243
|
-
📋 ROUND
|
|
247
|
+
📋 ROUND [current round]/3: Style Selection
|
|
244
248
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
→ Continue to STEP 2.2
|
|
252
|
+
|
|
253
|
+
### STEP 2.2: Build Style Options from Extracted Data
|
|
254
|
+
|
|
255
|
+
For each extracted site:
|
|
256
|
+
1. Extract the following information from the site's data:
|
|
257
|
+
- site: site name
|
|
258
|
+
- style: data.style.detected
|
|
259
|
+
- confidence: data.style.confidence
|
|
260
|
+
- characteristics: data.style.characteristics
|
|
261
|
+
- feel: data.style.feel
|
|
262
|
+
- colors: data.colors.primary
|
|
263
|
+
- animations: data.animation_libraries
|
|
264
|
+
- scrollPatterns: data.scroll_animations.patterns
|
|
265
|
+
- decorativeTypes: data.decorative_elements.types
|
|
266
|
+
2. Add to options list
|
|
267
|
+
|
|
268
|
+
→ Continue to STEP 2.3
|
|
269
|
+
|
|
270
|
+
### STEP 2.3: Calculate Match Scores
|
|
271
|
+
|
|
272
|
+
For each style option:
|
|
273
|
+
1. Start with base score = confidence value
|
|
274
|
+
2. Apply brand personality bonuses:
|
|
275
|
+
- **If brand includes "bold":**
|
|
276
|
+
- Add +15 if style is "Neo-Brutalism" or "Playful/Creative"
|
|
277
|
+
- **If brand includes "professional":**
|
|
278
|
+
- Add +15 if style is "Minimalist" or "Modern SaaS"
|
|
279
|
+
- **If brand includes "playful":**
|
|
280
|
+
- Add +15 if style is "Playful/Creative"
|
|
281
|
+
- **If brand includes "minimal":**
|
|
282
|
+
- Add +15 if style is "Minimalist"
|
|
283
|
+
3. Cap final score at 100 (max)
|
|
284
|
+
4. Store as matchScore
|
|
265
285
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
score += 15;
|
|
279
|
-
}
|
|
280
|
-
if (contextAnalysis.brand_personality.includes('playful') &&
|
|
281
|
-
opt.style === 'Playful/Creative') {
|
|
282
|
-
score += 15;
|
|
283
|
-
}
|
|
284
|
-
if (contextAnalysis.brand_personality.includes('minimal') &&
|
|
285
|
-
opt.style === 'Minimalist') {
|
|
286
|
-
score += 15;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return { ...opt, matchScore: Math.min(score, 100) };
|
|
291
|
-
}).sort((a, b) => b.matchScore - a.matchScore);
|
|
292
|
-
|
|
293
|
-
// Display verbose options
|
|
294
|
-
for (const [index, option] of scoredOptions.entries()) {
|
|
295
|
-
const letter = String.fromCharCode(65 + index);
|
|
296
|
-
const isRecommended = index === 0;
|
|
297
|
-
|
|
298
|
-
output(`
|
|
286
|
+
Sort all options by matchScore (highest first)
|
|
287
|
+
|
|
288
|
+
→ Continue to STEP 2.4
|
|
289
|
+
|
|
290
|
+
### STEP 2.4: Display Verbose Style Options
|
|
291
|
+
|
|
292
|
+
For each scored option (in sorted order):
|
|
293
|
+
1. Assign a letter (A, B, C, etc.)
|
|
294
|
+
2. Mark the first option (highest score) as "RECOMMENDED"
|
|
295
|
+
3. Display in this format:
|
|
296
|
+
|
|
297
|
+
```
|
|
299
298
|
┌─────────────────────────────────────────────────────────────┐
|
|
300
|
-
│ Option
|
|
301
|
-
│ Source:
|
|
302
|
-
│ Match Score:
|
|
299
|
+
│ Option [Letter]: [Style Name] [⭐ RECOMMENDED if first]
|
|
300
|
+
│ Source: [site name]
|
|
301
|
+
│ Match Score: [score]%
|
|
303
302
|
├─────────────────────────────────────────────────────────────┤
|
|
304
303
|
│
|
|
305
304
|
│ 📝 Characteristics:
|
|
306
|
-
│
|
|
305
|
+
│ • [characteristic 1]
|
|
306
|
+
│ • [characteristic 2]
|
|
307
|
+
│ ...
|
|
307
308
|
│
|
|
308
|
-
│ 🎭 Feel:
|
|
309
|
+
│ 🎭 Feel: [feel description]
|
|
309
310
|
│
|
|
310
|
-
│ 🎨 Colors:
|
|
311
|
+
│ 🎨 Colors: [primary colors list]
|
|
311
312
|
│
|
|
312
313
|
│ 🎬 Animations Available:
|
|
313
|
-
│
|
|
314
|
+
│ • [animation 1]
|
|
315
|
+
│ • [animation 2]
|
|
316
|
+
│ (or "(none detected)")
|
|
314
317
|
│
|
|
315
318
|
│ 📜 Scroll Patterns:
|
|
316
|
-
│
|
|
319
|
+
│ • [pattern 1]
|
|
320
|
+
│ • [pattern 2]
|
|
321
|
+
│ (or "(none detected)")
|
|
317
322
|
│
|
|
318
323
|
│ 🖼️ Decorative Elements:
|
|
319
|
-
│
|
|
324
|
+
│ • [element 1]
|
|
325
|
+
│ • [element 2]
|
|
326
|
+
│ (or "(none detected)")
|
|
320
327
|
│
|
|
321
328
|
└─────────────────────────────────────────────────────────────┘
|
|
322
|
-
|
|
323
|
-
}
|
|
329
|
+
```
|
|
324
330
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
พิมพ์ความต้องการ (ตัวอย่าง: "ชอบ border ของ A แต่อยากได้สี soft กว่านี้"):
|
|
344
|
-
`);
|
|
345
|
-
const customInput = await getUserTextInput();
|
|
346
|
-
|
|
347
|
-
// AI interprets and adjusts
|
|
348
|
-
output(`
|
|
349
|
-
🤖 กำลังปรับตาม feedback: "${customInput}"...
|
|
350
|
-
`);
|
|
351
|
-
|
|
352
|
-
round++;
|
|
353
|
-
continue; // Loop again with adjusted options
|
|
354
|
-
}
|
|
331
|
+
→ Continue to STEP 2.5
|
|
332
|
+
|
|
333
|
+
### STEP 2.5: Ask User to Select Style
|
|
334
|
+
|
|
335
|
+
Ask user to choose:
|
|
336
|
+
- Header: "Style"
|
|
337
|
+
- Single selection
|
|
338
|
+
- Options:
|
|
339
|
+
- For each scored option: "[Letter]: [Style Name]" - "[Score]% match - [Feel]"
|
|
340
|
+
- Last option: "Mix/Custom" - "ผสมหลาย style หรือปรับแต่งเอง"
|
|
341
|
+
|
|
342
|
+
**If user selects "Mix/Custom":**
|
|
343
|
+
1. Display prompt: "พิมพ์ความต้องการ (ตัวอย่าง: 'ชอบ border ของ A แต่อยากได้สี soft กว่านี้'):"
|
|
344
|
+
2. Get text input from user
|
|
345
|
+
3. Display: "🤖 กำลังปรับตาม feedback: '[input]'..."
|
|
346
|
+
4. Increment round counter
|
|
347
|
+
5. **If round <= 3:** → Go back to STEP 2.1 (new round with adjusted options)
|
|
348
|
+
6. **If round > 3:** → Continue to STEP 2.10 (max rounds reached)
|
|
355
349
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
350
|
+
**If user selects a specific style (A, B, C, etc.):**
|
|
351
|
+
1. Extract the letter (A=0, B=1, C=2, etc.)
|
|
352
|
+
2. Get the corresponding option from scored list
|
|
353
|
+
3. Store as selectedStyle
|
|
354
|
+
→ Continue to STEP 2.6
|
|
359
355
|
|
|
360
|
-
|
|
356
|
+
### STEP 2.6: Animation Selection
|
|
361
357
|
|
|
362
|
-
|
|
358
|
+
Display round header:
|
|
359
|
+
```
|
|
363
360
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
364
|
-
📋 ROUND
|
|
361
|
+
📋 ROUND [current round]/3: Animation Selection
|
|
365
362
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Step 2.6.1: Collect All Available Animations**
|
|
366
|
+
|
|
367
|
+
For each extracted site:
|
|
368
|
+
1. **From animation_libraries:**
|
|
369
|
+
- For each library: Add entry with type="library", name=lib.name, source=siteName, description="[lib.name] library detected"
|
|
370
|
+
|
|
371
|
+
2. **From scroll_animations.patterns:**
|
|
372
|
+
- For each pattern: Add entry with type="scroll", name=pattern, source=siteName, description="Scroll animation: [pattern]"
|
|
373
|
+
|
|
374
|
+
3. **From component_animations:**
|
|
375
|
+
- **If button_hover is not "none":**
|
|
376
|
+
- Add entry with type="component", name="Button: [button_hover]", source=siteName, description=button_hover value
|
|
377
|
+
- **If card_hover is not "none":**
|
|
378
|
+
- Add entry with type="component", name="Card: [card_hover]", source=siteName, description=card_hover value
|
|
379
|
+
|
|
380
|
+
**Step 2.6.2: Display Available Animations**
|
|
381
|
+
|
|
382
|
+
Display header: "🎬 Available Animations (จาก references ทั้งหมด):"
|
|
383
|
+
|
|
384
|
+
For each animation (numbered 1, 2, 3, etc.):
|
|
385
|
+
```
|
|
386
|
+
[number] [animation name]
|
|
387
|
+
Type: [type]
|
|
388
|
+
Source: [source site]
|
|
389
|
+
Description: [description]
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Step 2.6.3: Ask User to Select Animations**
|
|
393
|
+
|
|
394
|
+
Ask user to choose:
|
|
395
|
+
- Header: "Animations"
|
|
396
|
+
- Multiple selection allowed
|
|
397
|
+
- Question: "เลือก animations ที่ต้องการ (เลือกได้หลายอัน):"
|
|
398
|
+
- Options:
|
|
399
|
+
- For each animation: "[animation name]" - "From [source]: [description]"
|
|
400
|
+
|
|
401
|
+
Parse user's selections and store as selectedAnimations list
|
|
402
|
+
|
|
403
|
+
→ Continue to STEP 2.7
|
|
410
404
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
${allAnimations.map((anim, i) => `
|
|
416
|
-
[${i + 1}] ${anim.name}
|
|
417
|
-
Type: ${anim.type}
|
|
418
|
-
Source: ${anim.source}
|
|
419
|
-
Description: ${anim.description}
|
|
420
|
-
`).join('')}
|
|
421
|
-
`);
|
|
422
|
-
|
|
423
|
-
const animChoice = await AskUserQuestion({
|
|
424
|
-
questions: [{
|
|
425
|
-
question: "เลือก animations ที่ต้องการ (เลือกได้หลายอัน):",
|
|
426
|
-
header: "Animations",
|
|
427
|
-
multiSelect: true,
|
|
428
|
-
options: allAnimations.map((anim, i) => ({
|
|
429
|
-
label: `${anim.name}`,
|
|
430
|
-
description: `From ${anim.source}: ${anim.description}`
|
|
431
|
-
}))
|
|
432
|
-
}]
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
selectedAnimations = animChoice.answers["Animations"]
|
|
436
|
-
? animChoice.answers["Animations"].split(',').map(s => s.trim())
|
|
437
|
-
: [];
|
|
438
|
-
|
|
439
|
-
// ========== THEME + DECORATIVE DIRECTION ==========
|
|
440
|
-
|
|
441
|
-
output(`
|
|
405
|
+
### STEP 2.7: Theme & Decorative Direction
|
|
406
|
+
|
|
407
|
+
Display round header:
|
|
408
|
+
```
|
|
442
409
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
443
|
-
📋 ROUND
|
|
410
|
+
📋 ROUND [current round]/3: Theme & Decorative Direction
|
|
444
411
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
445
|
-
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Step 2.7.1: AI Theme Recommendations**
|
|
415
|
+
|
|
416
|
+
Ask Claude to recommend 3-4 theme options based on project context.
|
|
446
417
|
|
|
447
|
-
|
|
448
|
-
|
|
418
|
+
**Recommendation Prompt:**
|
|
419
|
+
```
|
|
449
420
|
Based on project context, recommend 3-4 theme options.
|
|
450
421
|
|
|
451
422
|
Project Context:
|
|
452
|
-
- Product Type:
|
|
453
|
-
- Target Audience:
|
|
454
|
-
- Brand Personality:
|
|
455
|
-
|
|
456
|
-
|
|
423
|
+
- Product Type: [from context analysis]
|
|
424
|
+
- Target Audience: [from context analysis]
|
|
425
|
+
- Brand Personality: [from context analysis]
|
|
426
|
+
[If context files exist: list context file names]
|
|
427
|
+
[If context files exist: include first 500 chars of first file]
|
|
457
428
|
|
|
458
429
|
Return JSON array:
|
|
459
430
|
[
|
|
@@ -467,148 +438,159 @@ Return JSON array:
|
|
|
467
438
|
"match_reason": "Why this theme fits the project"
|
|
468
439
|
}
|
|
469
440
|
]
|
|
470
|
-
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Parse the JSON response to get theme options list.
|
|
471
444
|
|
|
472
|
-
|
|
473
|
-
prompt: themePrompt,
|
|
474
|
-
response_format: 'json'
|
|
475
|
-
});
|
|
445
|
+
**Step 2.7.2: Display Theme Options**
|
|
476
446
|
|
|
477
|
-
|
|
478
|
-
🎨 Theme Recommendations (based on your project):
|
|
479
|
-
`);
|
|
447
|
+
Display header: "🎨 Theme Recommendations (based on your project):"
|
|
480
448
|
|
|
481
|
-
|
|
482
|
-
|
|
449
|
+
For each theme option:
|
|
450
|
+
```
|
|
483
451
|
┌─────────────────────────────────────────────────────────────┐
|
|
484
|
-
│ Theme
|
|
452
|
+
│ Theme [Letter]: [theme name]
|
|
485
453
|
├─────────────────────────────────────────────────────────────┤
|
|
486
454
|
│
|
|
487
|
-
│ 📝 Description:
|
|
488
|
-
│ 🎭 Feeling:
|
|
455
|
+
│ 📝 Description: [description]
|
|
456
|
+
│ 🎭 Feeling: [feeling]
|
|
489
457
|
│
|
|
490
458
|
│ ✅ Decorative Elements (Use):
|
|
491
|
-
│
|
|
459
|
+
│ • [element 1]
|
|
460
|
+
│ • [element 2]
|
|
461
|
+
│ ...
|
|
492
462
|
│
|
|
493
463
|
│ ❌ Avoid:
|
|
494
|
-
│
|
|
464
|
+
│ • [avoid 1]
|
|
465
|
+
│ • [avoid 2]
|
|
466
|
+
│ ...
|
|
495
467
|
│
|
|
496
|
-
│ 🎯 Icons (Lucide):
|
|
468
|
+
│ 🎯 Icons (Lucide): [icons list]
|
|
497
469
|
│
|
|
498
|
-
│ 💡 Why:
|
|
470
|
+
│ 💡 Why: [match_reason]
|
|
499
471
|
│
|
|
500
472
|
└─────────────────────────────────────────────────────────────┘
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const themeChoice = await AskUserQuestion({
|
|
505
|
-
questions: [{
|
|
506
|
-
question: "เลือก theme หรือพิมพ์ custom:",
|
|
507
|
-
header: "Theme",
|
|
508
|
-
multiSelect: false,
|
|
509
|
-
options: [
|
|
510
|
-
...themeOptions.map((t, i) => ({
|
|
511
|
-
label: `${String.fromCharCode(65 + i)}: ${t.name}`,
|
|
512
|
-
description: `${t.feeling} - ${t.decorative_elements.slice(0, 3).join(', ')}`
|
|
513
|
-
})),
|
|
514
|
-
{ label: "No Theme", description: "ไม่ใช้ theme - geometric/abstract" },
|
|
515
|
-
{ label: "Custom", description: "กำหนด theme เอง" }
|
|
516
|
-
]
|
|
517
|
-
}]
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
if (themeChoice.answers["Theme"] === "Custom") {
|
|
521
|
-
output(`พิมพ์ theme ที่ต้องการ (ตัวอย่าง: "อวกาศ - จรวด, ดาวเทียม, ดาว"):`);
|
|
522
|
-
const customTheme = await getUserTextInput();
|
|
523
|
-
selectedTheme = {
|
|
524
|
-
name: 'Custom',
|
|
525
|
-
description: customTheme,
|
|
526
|
-
decorative_elements: customTheme.split(',').map(s => s.trim()),
|
|
527
|
-
avoid_elements: []
|
|
528
|
-
};
|
|
529
|
-
} else if (themeChoice.answers["Theme"] === "No Theme") {
|
|
530
|
-
selectedTheme = {
|
|
531
|
-
name: 'Abstract',
|
|
532
|
-
description: 'No specific theme - geometric and abstract decorations',
|
|
533
|
-
decorative_elements: ['geometric shapes', 'gradients', 'blobs'],
|
|
534
|
-
avoid_elements: []
|
|
535
|
-
};
|
|
536
|
-
} else {
|
|
537
|
-
const themeIndex = themeChoice.answers["Theme"].charCodeAt(0) - 65;
|
|
538
|
-
selectedTheme = themeOptions[themeIndex];
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// ========== CONFIRMATION ==========
|
|
473
|
+
```
|
|
542
474
|
|
|
543
|
-
|
|
475
|
+
**Step 2.7.3: Ask User to Select Theme**
|
|
476
|
+
|
|
477
|
+
Ask user to choose:
|
|
478
|
+
- Header: "Theme"
|
|
479
|
+
- Single selection
|
|
480
|
+
- Question: "เลือก theme หรือพิมพ์ custom:"
|
|
481
|
+
- Options:
|
|
482
|
+
- For each theme: "[Letter]: [name]" - "[feeling] - [first 3 decorative elements]"
|
|
483
|
+
- "No Theme" - "ไม่ใช้ theme - geometric/abstract"
|
|
484
|
+
- "Custom" - "กำหนด theme เอง"
|
|
485
|
+
|
|
486
|
+
**If user selects "Custom":**
|
|
487
|
+
1. Display prompt: "พิมพ์ theme ที่ต้องการ (ตัวอย่าง: 'อวกาศ - จรวด, ดาวเทียม, ดาว'):"
|
|
488
|
+
2. Get text input from user
|
|
489
|
+
3. Build custom theme:
|
|
490
|
+
- name: "Custom"
|
|
491
|
+
- description: [user input]
|
|
492
|
+
- decorative_elements: [split user input by comma and trim]
|
|
493
|
+
- avoid_elements: []
|
|
494
|
+
4. Store as selectedTheme
|
|
495
|
+
|
|
496
|
+
**If user selects "No Theme":**
|
|
497
|
+
1. Build abstract theme:
|
|
498
|
+
- name: "Abstract"
|
|
499
|
+
- description: "No specific theme - geometric and abstract decorations"
|
|
500
|
+
- decorative_elements: ["geometric shapes", "gradients", "blobs"]
|
|
501
|
+
- avoid_elements: []
|
|
502
|
+
2. Store as selectedTheme
|
|
503
|
+
|
|
504
|
+
**If user selects a specific theme (A, B, C, etc.):**
|
|
505
|
+
1. Extract the letter (A=0, B=1, C=2, etc.)
|
|
506
|
+
2. Get the corresponding theme from options list
|
|
507
|
+
3. Store as selectedTheme
|
|
508
|
+
|
|
509
|
+
→ Continue to STEP 2.8
|
|
510
|
+
|
|
511
|
+
### STEP 2.8: Display Summary and Confirmation
|
|
512
|
+
|
|
513
|
+
Display summary header:
|
|
514
|
+
```
|
|
544
515
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
545
516
|
✅ SUMMARY - Please Confirm
|
|
546
517
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
547
518
|
|
|
548
|
-
🎨 Style:
|
|
549
|
-
Feel:
|
|
519
|
+
🎨 Style: [selectedStyle.style] (from [selectedStyle.site])
|
|
520
|
+
Feel: [selectedStyle.feel]
|
|
550
521
|
|
|
551
522
|
🎬 Animations Enabled:
|
|
552
|
-
|
|
523
|
+
✅ [animation 1]
|
|
524
|
+
✅ [animation 2]
|
|
525
|
+
(or "(none selected)" if empty)
|
|
553
526
|
|
|
554
|
-
🎭 Theme:
|
|
555
|
-
Decorations:
|
|
556
|
-
Avoid:
|
|
527
|
+
🎭 Theme: [selectedTheme.name]
|
|
528
|
+
Decorations: [decorative_elements list]
|
|
529
|
+
Avoid: [avoid_elements list or "(none)"]
|
|
557
530
|
|
|
558
531
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
**Step 2.8.1: Ask User to Confirm**
|
|
535
|
+
|
|
536
|
+
Ask user to confirm:
|
|
537
|
+
- Header: "Confirm"
|
|
538
|
+
- Single selection
|
|
539
|
+
- Question: "ยืนยันการตั้งค่านี้?"
|
|
540
|
+
- Options:
|
|
541
|
+
- "Yes, Generate" - "สร้าง design system ตามนี้"
|
|
542
|
+
- "Adjust" - "ปรับแต่งอีกรอบ"
|
|
543
|
+
- "Start Over" - "เริ่มใหม่ตั้งแต่ต้น"
|
|
544
|
+
|
|
545
|
+
**If user selects "Yes, Generate":**
|
|
546
|
+
- Mark as accepted
|
|
547
|
+
→ Exit loop, continue to STEP 3
|
|
548
|
+
|
|
549
|
+
**If user selects "Start Over":**
|
|
550
|
+
- Reset round counter to 1
|
|
551
|
+
→ Go back to STEP 2.1 (start fresh)
|
|
552
|
+
|
|
553
|
+
**If user selects "Adjust":**
|
|
554
|
+
- Increment round counter
|
|
555
|
+
→ Continue to STEP 2.9 (check round limit)
|
|
556
|
+
|
|
557
|
+
### STEP 2.9: Check Round Limit
|
|
558
|
+
|
|
559
|
+
**If current round <= 3:**
|
|
560
|
+
→ Go back to STEP 2.1 (new adjustment round)
|
|
561
|
+
|
|
562
|
+
**If current round > 3 (max rounds reached):**
|
|
563
|
+
→ Continue to STEP 2.10
|
|
581
564
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
565
|
+
### STEP 2.10: Max Rounds Reached - Force Decision
|
|
566
|
+
|
|
567
|
+
Display warning:
|
|
568
|
+
```
|
|
569
|
+
⚠️ ครบ 3 รอบแล้ว
|
|
585
570
|
|
|
586
571
|
แนะนำ:
|
|
587
572
|
1. รัน /extract กับ reference ใหม่
|
|
588
573
|
2. หรือ accept แล้วค่อย manual edit ไฟล์ที่สร้าง
|
|
589
|
-
`);
|
|
590
|
-
|
|
591
|
-
const forceChoice = await AskUserQuestion({
|
|
592
|
-
questions: [{
|
|
593
|
-
question: "ต้องการ generate ตาม settings ปัจจุบันไหม?",
|
|
594
|
-
header: "Force",
|
|
595
|
-
multiSelect: false,
|
|
596
|
-
options: [
|
|
597
|
-
{ label: "Yes", description: "Generate ตาม settings ล่าสุด" },
|
|
598
|
-
{ label: "Cancel", description: "ยกเลิก" }
|
|
599
|
-
]
|
|
600
|
-
}]
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
if (forceChoice.answers["Force"] === "Yes") {
|
|
604
|
-
userAccepted = true;
|
|
605
|
-
} else {
|
|
606
|
-
return output('Design setup cancelled.');
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
574
|
```
|
|
611
575
|
|
|
576
|
+
Ask user for final decision:
|
|
577
|
+
- Header: "Force"
|
|
578
|
+
- Single selection
|
|
579
|
+
- Question: "ต้องการ generate ตาม settings ปัจจุบันไหม?"
|
|
580
|
+
- Options:
|
|
581
|
+
- "Yes" - "Generate ตาม settings ล่าสุด"
|
|
582
|
+
- "Cancel" - "ยกเลิก"
|
|
583
|
+
|
|
584
|
+
**If user selects "Yes":**
|
|
585
|
+
- Mark as accepted
|
|
586
|
+
→ Continue to STEP 3
|
|
587
|
+
|
|
588
|
+
**If user selects "Cancel":**
|
|
589
|
+
- Display: "Design setup cancelled."
|
|
590
|
+
→ STOP (exit command)
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
612
594
|
**Report:**
|
|
613
595
|
```
|
|
614
596
|
✅ User Selection Complete!
|
|
@@ -622,1734 +604,800 @@ ${selectedAnimations.map(a => ` ✅ ${a}`).join('\n') || ' (none selected)'}
|
|
|
622
604
|
|
|
623
605
|
---
|
|
624
606
|
|
|
625
|
-
## STEP 3: Generate Preview YAMLs
|
|
607
|
+
## STEP 3: Generate Preview YAMLs (Legacy - Optional)
|
|
608
|
+
|
|
609
|
+
> **Note:** This step is optional and creates preview files for each option. In the new flow, we skip directly to generating the final files.
|
|
626
610
|
|
|
627
|
-
|
|
611
|
+
**If you want to generate preview files:**
|
|
628
612
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
613
|
+
For each style option that was presented to the user:
|
|
614
|
+
1. Assign a letter (A, B, C, etc.)
|
|
615
|
+
2. Ask Claude to generate an abbreviated YAML preview
|
|
632
616
|
|
|
633
|
-
|
|
617
|
+
**Preview Generation Prompt:**
|
|
618
|
+
```
|
|
634
619
|
You are generating a preview style guide in YAML format.
|
|
635
620
|
|
|
636
|
-
Style Direction:
|
|
637
|
-
Fit Score:
|
|
638
|
-
Rationale:
|
|
621
|
+
Style Direction: [option.name]
|
|
622
|
+
Fit Score: [option.fit_score]%
|
|
623
|
+
Rationale: [option.rationale]
|
|
639
624
|
|
|
640
625
|
Source Mapping:
|
|
641
|
-
|
|
626
|
+
[JSON of option.sources]
|
|
642
627
|
|
|
643
628
|
Customizations:
|
|
644
|
-
|
|
629
|
+
[list of option.customizations]
|
|
645
630
|
|
|
646
631
|
Extracted Data (for reference):
|
|
647
|
-
|
|
632
|
+
[First 5000 chars of extractedData JSON]
|
|
648
633
|
|
|
649
634
|
Task: Create abbreviated YAML preview with key values only.
|
|
650
635
|
|
|
651
636
|
Format:
|
|
652
|
-
|
|
637
|
+
```yaml
|
|
653
638
|
meta:
|
|
654
|
-
style_name: "
|
|
655
|
-
fit_score:
|
|
639
|
+
style_name: "[option.name]"
|
|
640
|
+
fit_score: [option.fit_score]
|
|
656
641
|
sources: [list of source sites]
|
|
657
642
|
|
|
658
643
|
colors:
|
|
659
644
|
primary:
|
|
660
|
-
hex: "#..." # From
|
|
645
|
+
hex: "#..." # From [option.sources.colors]
|
|
661
646
|
rationale: "Why this color fits"
|
|
662
647
|
secondary:
|
|
663
648
|
hex: "#..."
|
|
664
649
|
# ... 5-10 key colors
|
|
665
650
|
|
|
666
651
|
typography:
|
|
667
|
-
font_family: "..." # From
|
|
652
|
+
font_family: "..." # From [option.sources.typography]
|
|
668
653
|
h1: { size: "...", weight: "..." }
|
|
669
654
|
# ... key type styles
|
|
670
655
|
|
|
671
656
|
shadows:
|
|
672
|
-
brutal: "..." # From
|
|
657
|
+
brutal: "..." # From [option.sources.shadows]
|
|
673
658
|
# ... 3-5 key shadows
|
|
674
659
|
|
|
675
660
|
spacing:
|
|
676
|
-
grid: "..." # From
|
|
661
|
+
grid: "..." # From [option.sources.spacing]
|
|
677
662
|
|
|
678
663
|
components:
|
|
679
664
|
button:
|
|
680
|
-
hover_animation: "..." # From
|
|
665
|
+
hover_animation: "..." # From [option.sources.button_hover]
|
|
681
666
|
description: "..."
|
|
682
667
|
card:
|
|
683
|
-
hover_animation: "..." # From
|
|
668
|
+
hover_animation: "..." # From [option.sources.card_hover]
|
|
684
669
|
# ... key components
|
|
685
670
|
|
|
686
671
|
border_radius:
|
|
687
|
-
values: [...] # From
|
|
688
|
-
|
|
672
|
+
values: [...] # From [option.sources.border_radius]
|
|
673
|
+
```
|
|
689
674
|
|
|
690
675
|
Return only the YAML content.
|
|
691
|
-
|
|
676
|
+
```
|
|
692
677
|
|
|
693
|
-
|
|
678
|
+
3. Write the preview to file:
|
|
679
|
+
- Path: `design-system/synthesis/options/option-[letter]-[name-kebab-case].yaml`
|
|
680
|
+
- Content: YAML from Claude's response
|
|
694
681
|
|
|
695
|
-
|
|
696
|
-
`design-system/synthesis/options/option-${optionLetter.toLowerCase()}-${option.name.toLowerCase().replace(/\s+/g, '-')}.yaml`,
|
|
697
|
-
previewYAML
|
|
698
|
-
);
|
|
699
|
-
}
|
|
700
|
-
```
|
|
682
|
+
**Skip this step in most cases** - proceed directly to STEP 3.5
|
|
701
683
|
|
|
702
684
|
---
|
|
703
685
|
|
|
704
|
-
## STEP 3.5: Quick User Input (
|
|
686
|
+
## STEP 3.5: Quick User Input (Legacy - v1.4.0)
|
|
687
|
+
|
|
688
|
+
> **Note:** This step is from an older version and asks for preferences before presenting options. This is now integrated into STEP 2's interactive loop. Can be skipped.
|
|
705
689
|
|
|
706
|
-
|
|
690
|
+
**If you want to collect user preferences upfront:**
|
|
707
691
|
|
|
708
|
-
|
|
709
|
-
|
|
692
|
+
Display header:
|
|
693
|
+
```
|
|
710
694
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
711
695
|
📝 Quick Question
|
|
712
696
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
const userFeedback = await AskUserQuestion({
|
|
716
|
-
questions: [{
|
|
717
|
-
question: "มีอะไรอยากปรับหรือเน้นเป็นพิเศษไหม? (optional)",
|
|
718
|
-
header: "Preferences",
|
|
719
|
-
multiSelect: false,
|
|
720
|
-
options: [
|
|
721
|
-
{ label: "ไม่มี ใช้ AI แนะนำ", description: "ให้ AI เลือกสิ่งที่เหมาะสมที่สุด" },
|
|
722
|
-
{ label: "มีสี CI ของตัวเอง", description: "ระบุสีแบรนด์" },
|
|
723
|
-
{ label: "ชอบ component เฉพาะ", description: "ชอบ button/card ของเว็บใดเป็นพิเศษ" },
|
|
724
|
-
{ label: "ปรับอื่นๆ", description: "Typography, shadows, หรืออื่นๆ" }
|
|
725
|
-
]
|
|
726
|
-
}]
|
|
727
|
-
})
|
|
728
|
-
|
|
729
|
-
let userPreferences = { type: 'none' }
|
|
730
|
-
|
|
731
|
-
// Process user feedback
|
|
732
|
-
if (userFeedback.answers["Preferences"] === "มีสี CI ของตัวเอง") {
|
|
733
|
-
output(`
|
|
734
|
-
กรุณาระบุสี (HEX format, คั่นด้วย comma):
|
|
735
|
-
ตัวอย่าง: #0d7276, #f97316
|
|
736
|
-
|
|
737
|
-
สีของคุณ:
|
|
738
|
-
`)
|
|
739
|
-
|
|
740
|
-
const colorInput = await getUserTextInput()
|
|
741
|
-
const colors = colorInput.split(',').map(s => s.trim()).filter(s => s.match(/^#[0-9A-Fa-f]{6}$/))
|
|
742
|
-
|
|
743
|
-
if (colors.length > 0) {
|
|
744
|
-
userPreferences = {
|
|
745
|
-
type: 'custom_colors',
|
|
746
|
-
colors: {
|
|
747
|
-
primary: colors[0],
|
|
748
|
-
secondary: colors[1] || null,
|
|
749
|
-
accent: colors[2] || null
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
output(`✅ รับสีแล้ว: ${colors.join(', ')}`)
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
} else if (userFeedback.answers["Preferences"] === "ชอบ component เฉพาะ") {
|
|
756
|
-
output(`
|
|
757
|
-
ระบุความชอบ (ตัวอย่าง: "ชอบ button ของ motherduck, card ของ gitingest"):
|
|
758
|
-
`)
|
|
759
|
-
|
|
760
|
-
const preferenceText = await getUserTextInput()
|
|
761
|
-
userPreferences = {
|
|
762
|
-
type: 'component_preference',
|
|
763
|
-
text: preferenceText
|
|
764
|
-
}
|
|
765
|
-
output(`✅ บันทึกความชอบแล้ว`)
|
|
766
|
-
|
|
767
|
-
} else if (userFeedback.answers["Preferences"] === "ปรับอื่นๆ") {
|
|
768
|
-
output(`
|
|
769
|
-
ระบุสิ่งที่อยากปรับ (ตัวอย่าง: "ใช้ font Inter, shadow แบบ soft"):
|
|
770
|
-
`)
|
|
771
|
-
|
|
772
|
-
const adjustmentText = await getUserTextInput()
|
|
773
|
-
userPreferences = {
|
|
774
|
-
type: 'other_adjustment',
|
|
775
|
-
text: adjustmentText
|
|
776
|
-
}
|
|
777
|
-
output(`✅ บันทึกการปรับแต่งแล้ว`)
|
|
778
|
-
}
|
|
697
|
+
```
|
|
779
698
|
|
|
780
|
-
|
|
699
|
+
Ask user about special preferences:
|
|
700
|
+
- Header: "Preferences"
|
|
701
|
+
- Single selection
|
|
702
|
+
- Question: "มีอะไรอยากปรับหรือเน้นเป็นพิเศษไหม? (optional)"
|
|
703
|
+
- Options:
|
|
704
|
+
- "ไม่มี ใช้ AI แนะนำ" - "ให้ AI เลือกสิ่งที่เหมาะสมที่สุด"
|
|
705
|
+
- "มีสี CI ของตัวเอง" - "ระบุสีแบรนด์"
|
|
706
|
+
- "ชอบ component เฉพาะ" - "ชอบ button/card ของเว็บใดเป็นพิเศษ"
|
|
707
|
+
- "ปรับอื่นๆ" - "Typography, shadows, หรืออื่นๆ"
|
|
708
|
+
|
|
709
|
+
Initialize userPreferences with type: 'none'
|
|
710
|
+
|
|
711
|
+
**If user selects "มีสี CI ของตัวเอง":**
|
|
712
|
+
1. Display prompt:
|
|
713
|
+
```
|
|
714
|
+
กรุณาระบุสี (HEX format, คั่นด้วย comma):
|
|
715
|
+
ตัวอย่าง: #0d7276, #f97316
|
|
716
|
+
|
|
717
|
+
สีของคุณ:
|
|
718
|
+
```
|
|
719
|
+
2. Get text input from user
|
|
720
|
+
3. Parse colors: split by comma, trim, filter only valid HEX format (#RRGGBB)
|
|
721
|
+
4. **If valid colors found:**
|
|
722
|
+
- Set userPreferences.type = 'custom_colors'
|
|
723
|
+
- Set userPreferences.colors.primary = first color
|
|
724
|
+
- Set userPreferences.colors.secondary = second color (or null)
|
|
725
|
+
- Set userPreferences.colors.accent = third color (or null)
|
|
726
|
+
- Display: "✅ รับสีแล้ว: [colors list]"
|
|
727
|
+
|
|
728
|
+
**If user selects "ชอบ component เฉพาะ":**
|
|
729
|
+
1. Display prompt: "ระบุความชอบ (ตัวอย่าง: 'ชอบ button ของ motherduck, card ของ gitingest'):"
|
|
730
|
+
2. Get text input from user
|
|
731
|
+
3. Set userPreferences.type = 'component_preference'
|
|
732
|
+
4. Set userPreferences.text = user input
|
|
733
|
+
5. Display: "✅ บันทึกความชอบแล้ว"
|
|
734
|
+
|
|
735
|
+
**If user selects "ปรับอื่นๆ":**
|
|
736
|
+
1. Display prompt: "ระบุสิ่งที่อยากปรับ (ตัวอย่าง: 'ใช้ font Inter, shadow แบบ soft'):"
|
|
737
|
+
2. Get text input from user
|
|
738
|
+
3. Set userPreferences.type = 'other_adjustment'
|
|
739
|
+
4. Set userPreferences.text = user input
|
|
740
|
+
5. Display: "✅ บันทึกการปรับแต่งแล้ว"
|
|
741
|
+
|
|
742
|
+
Display final message:
|
|
743
|
+
```
|
|
781
744
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
782
745
|
🔄 กำลังสร้าง style options (พร้อม preferences ของคุณ)...
|
|
783
746
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
784
|
-
`)
|
|
785
747
|
```
|
|
786
748
|
|
|
749
|
+
**In most cases, skip this step** - preferences are handled in STEP 2's interactive loop
|
|
750
|
+
|
|
787
751
|
---
|
|
788
752
|
|
|
789
|
-
## STEP 4: Present Options to User
|
|
753
|
+
## STEP 4: Present Options to User (Legacy - Old Flow)
|
|
754
|
+
|
|
755
|
+
> **Note:** This step is from the old flow (v1.x). In the new flow (v2.0+), user selection happens in STEP 2's interactive loop. This step is now DEPRECATED.
|
|
790
756
|
|
|
791
|
-
|
|
792
|
-
|
|
757
|
+
**Old flow (for reference only):**
|
|
758
|
+
|
|
759
|
+
Display analysis summary:
|
|
760
|
+
```
|
|
793
761
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
794
762
|
🎨 Design Direction Analysis Complete
|
|
795
763
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
796
764
|
|
|
797
765
|
Based on:
|
|
798
|
-
✓
|
|
799
|
-
✓ Target:
|
|
800
|
-
✓ Brand:
|
|
801
|
-
✓ Product:
|
|
802
|
-
|
|
766
|
+
✓ [number] extracted sites ([site names])
|
|
767
|
+
✓ Target: [target audience]
|
|
768
|
+
✓ Brand: [brand personality]
|
|
769
|
+
✓ Product: [product type]
|
|
770
|
+
[If preferences: ✓ User preferences: [preferences]]
|
|
803
771
|
|
|
804
772
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
for (const [index, option] of styleOptions.options.entries()) {
|
|
808
|
-
const optionLetter = String.fromCharCode(65 + index);
|
|
809
|
-
const isRecommended = index === 0;
|
|
773
|
+
```
|
|
810
774
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
775
|
+
For each style option:
|
|
776
|
+
Display:
|
|
777
|
+
```
|
|
778
|
+
Option [Letter]: [option.name] [⭐ (Recommended) if first]
|
|
779
|
+
Fit Score: [option.fit_score]%
|
|
814
780
|
|
|
815
781
|
Rationale:
|
|
816
|
-
|
|
782
|
+
[option.rationale]
|
|
817
783
|
|
|
818
784
|
Component Sources:
|
|
819
|
-
- Colors:
|
|
820
|
-
- Shadows:
|
|
821
|
-
- Typography:
|
|
822
|
-
- Button hover:
|
|
823
|
-
- Card hover:
|
|
824
|
-
- Input focus:
|
|
825
|
-
- Border radius:
|
|
826
|
-
- Overall vibe:
|
|
785
|
+
- Colors: [option.sources.colors]
|
|
786
|
+
- Shadows: [option.sources.shadows]
|
|
787
|
+
- Typography: [option.sources.typography]
|
|
788
|
+
- Button hover: [option.sources.button_hover]
|
|
789
|
+
- Card hover: [option.sources.card_hover]
|
|
790
|
+
- Input focus: [option.sources.input_focus]
|
|
791
|
+
- Border radius: [option.sources.border_radius]
|
|
792
|
+
- Overall vibe: [option.sources.overall_vibe]
|
|
827
793
|
|
|
828
794
|
Customizations Applied:
|
|
829
|
-
|
|
795
|
+
• [customization 1]
|
|
796
|
+
• [customization 2]
|
|
797
|
+
...
|
|
830
798
|
|
|
831
799
|
Advantages:
|
|
832
|
-
|
|
800
|
+
✅ [advantage 1]
|
|
801
|
+
✅ [advantage 2]
|
|
802
|
+
...
|
|
833
803
|
|
|
834
804
|
Disadvantages:
|
|
835
|
-
|
|
805
|
+
⚠️ [disadvantage 1]
|
|
806
|
+
⚠️ [disadvantage 2]
|
|
807
|
+
...
|
|
836
808
|
|
|
837
|
-
Preview: design-system/synthesis/options/option
|
|
809
|
+
Preview: design-system/synthesis/options/option-[letter]-[name-kebab].yaml
|
|
838
810
|
|
|
839
811
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
840
|
-
|
|
841
|
-
}
|
|
812
|
+
```
|
|
842
813
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
options: styleOptions.options.map((opt, i) => ({
|
|
850
|
-
label: `${String.fromCharCode(65 + i)}: ${opt.name}`,
|
|
851
|
-
description: `${opt.fit_score}% fit - ${opt.rationale.substring(0, 100)}...`
|
|
852
|
-
}))
|
|
853
|
-
}]
|
|
854
|
-
});
|
|
814
|
+
Ask user to select:
|
|
815
|
+
- Header: "Style"
|
|
816
|
+
- Single selection
|
|
817
|
+
- Question: "Select design direction:"
|
|
818
|
+
- Options:
|
|
819
|
+
- For each option: "[Letter]: [name]" - "[score]% fit - [first 100 chars of rationale]..."
|
|
855
820
|
|
|
856
|
-
|
|
857
|
-
const selectedOption = styleOptions.options[selectedIndex];
|
|
858
|
-
```
|
|
821
|
+
Extract selected index and get corresponding option.
|
|
859
822
|
|
|
860
823
|
**Report:**
|
|
861
824
|
```
|
|
862
|
-
✅ Style Selected:
|
|
825
|
+
✅ Style Selected: [selectedOption.name]
|
|
863
826
|
|
|
864
827
|
🔄 Generating comprehensive design system...
|
|
865
828
|
```
|
|
866
829
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
## STEP 5: Generate Final Design System (Legacy - See STEP 5.7)
|
|
870
|
-
|
|
871
|
-
```javascript
|
|
872
|
-
const styleGuidePrompt = `
|
|
873
|
-
You are generating the final, comprehensive design system file.
|
|
874
|
-
|
|
875
|
-
Selected Style: ${selectedOption.name}
|
|
876
|
-
Fit Score: ${selectedOption.fit_score}%
|
|
877
|
-
Rationale: ${selectedOption.rationale}
|
|
878
|
-
|
|
879
|
-
Source Mapping:
|
|
880
|
-
${JSON.stringify(selectedOption.sources, null, 2)}
|
|
881
|
-
|
|
882
|
-
Customizations:
|
|
883
|
-
${selectedOption.customizations.join('\n')}
|
|
884
|
-
|
|
885
|
-
Full Extracted Data:
|
|
886
|
-
${JSON.stringify(extractedData, null, 2)}
|
|
887
|
-
|
|
888
|
-
Preview YAML:
|
|
889
|
-
${Read(`design-system/synthesis/options/option-${String.fromCharCode(65 + selectedIndex).toLowerCase()}-${selectedOption.name.toLowerCase().replace(/\s+/g, '-')}.yaml`)}
|
|
890
|
-
|
|
891
|
-
Project Context:
|
|
892
|
-
- Product: ${contextAnalysis.product_type}
|
|
893
|
-
- Audience: ${contextAnalysis.target_audience.demographics}
|
|
894
|
-
- Brand: ${contextAnalysis.brand_personality.join(', ')}
|
|
895
|
-
|
|
896
|
-
Task: Generate complete design system (1500-2000 lines) with ALL 17 sections.
|
|
897
|
-
|
|
898
|
-
Follow this format:
|
|
899
|
-
|
|
900
|
-
# [Project Name] Design System - Style Guide (${selectedOption.name})
|
|
901
|
-
|
|
902
|
-
> **Source:** Based on ${Object.keys(extractedData).join(', ')}, customized for [Project]
|
|
903
|
-
> **Date:** ${new Date().toISOString().split('T')[0]}
|
|
904
|
-
> **Design Style:** ${selectedOption.name}
|
|
905
|
-
> **Tech Stack:** Universal (Framework-agnostic)
|
|
906
|
-
> **Primary Color:** [from preview YAML]
|
|
907
|
-
|
|
908
|
-
---
|
|
909
|
-
|
|
910
|
-
## Quick Reference
|
|
911
|
-
|
|
912
|
-
### Most Used Patterns
|
|
913
|
-
|
|
914
|
-
| Pattern | Code |
|
|
915
|
-
|---------|------|
|
|
916
|
-
[Table with most-used component patterns with exact Tailwind classes]
|
|
917
|
-
|
|
918
|
-
### Design Tokens Summary
|
|
919
|
-
|
|
920
|
-
\`\`\`json
|
|
921
|
-
{
|
|
922
|
-
"colors": { ... },
|
|
923
|
-
"spacing": { ... },
|
|
924
|
-
"typography": { ... },
|
|
925
|
-
"borderRadius": { ... },
|
|
926
|
-
"shadows": { ... }
|
|
927
|
-
}
|
|
928
|
-
\`\`\`
|
|
830
|
+
**In current version (v2.0+), skip this step** - user selection is handled in STEP 2
|
|
929
831
|
|
|
930
832
|
---
|
|
931
833
|
|
|
932
|
-
##
|
|
933
|
-
|
|
934
|
-
1. [Overview](#1-overview)
|
|
935
|
-
2. [Design Philosophy](#2-design-philosophy)
|
|
936
|
-
3. [Color Palette](#3-color-palette)
|
|
937
|
-
... (all 17)
|
|
938
|
-
|
|
939
|
-
---
|
|
940
|
-
|
|
941
|
-
## 1. Overview
|
|
942
|
-
|
|
943
|
-
**Summary:**
|
|
944
|
-
This design system is based on **${selectedOption.name}** aesthetics...
|
|
945
|
-
|
|
946
|
-
**Key Characteristics:**
|
|
947
|
-
- [List from extracted data + customizations]
|
|
948
|
-
|
|
949
|
-
**Tech Stack:**
|
|
950
|
-
- Framework: Universal
|
|
951
|
-
- Styling: Tailwind CSS recommended
|
|
952
|
-
- Font: [from typography source]
|
|
953
|
-
|
|
954
|
-
**Goals:**
|
|
955
|
-
- [Derived from rationale + advantages]
|
|
956
|
-
|
|
957
|
-
---
|
|
834
|
+
## STEP 5: Generate Final Design System (Legacy - Deprecated in v2.0+)
|
|
958
835
|
|
|
959
|
-
|
|
836
|
+
> **Note:** This step is from the old flow (v1.x). In the current flow (v2.0+), design system generation happens in STEP 5.5 (data.yaml), STEP 5.6 (patterns/*.md), and STEP 5.7 (README.md). This step is now DEPRECATED.
|
|
960
837
|
|
|
961
|
-
**
|
|
838
|
+
**Old flow (for reference only):**
|
|
962
839
|
|
|
963
|
-
|
|
964
|
-
- [Description]
|
|
840
|
+
This step would generate a comprehensive 1500-2000 line README.md by:
|
|
965
841
|
|
|
966
|
-
|
|
967
|
-
-
|
|
842
|
+
1. Preparing a prompt for Claude with:
|
|
843
|
+
- Selected option details (name, fit score, rationale)
|
|
844
|
+
- Source mapping (which site provided which design elements)
|
|
845
|
+
- Customizations applied
|
|
846
|
+
- Full extracted data from all sites
|
|
847
|
+
- Preview YAML content
|
|
848
|
+
- Project context (product type, audience, brand)
|
|
968
849
|
|
|
969
|
-
|
|
850
|
+
2. The prompt would request a complete design system markdown file with:
|
|
851
|
+
- Header with metadata (source, date, style, tech stack, primary color)
|
|
852
|
+
- Quick reference section (most-used patterns table, design tokens JSON)
|
|
853
|
+
- Table of contents (all 17 sections)
|
|
854
|
+
- Section 1: Overview (summary, characteristics, tech stack, goals)
|
|
855
|
+
- Section 2: Design Philosophy (core principles, visual identity, differentiators, UX goals)
|
|
856
|
+
- Section 3: Color Palette (primary/secondary colors with hex, usage, psychology, source, CSS variables, Tailwind classes)
|
|
857
|
+
- Section 4: Typography (font family, weights, text styles for all headings with exact Tailwind classes and sources)
|
|
858
|
+
- Section 5: Spacing System (grid base, scale array from source)
|
|
859
|
+
- Section 6: Component Styles (buttons, cards, etc. with exact classes, animations, sources)
|
|
860
|
+
- Section 7: Shadows & Elevation (levels and usage from source)
|
|
861
|
+
- Sections 8-16: [Other design system sections]
|
|
862
|
+
- Section 17: Additional Sections (implementation best practices, accessibility guidelines, critical DO/DON'T rules)
|
|
863
|
+
- Footer with project name, date, sources
|
|
970
864
|
|
|
971
|
-
|
|
972
|
-
${selectedOption.rationale}
|
|
865
|
+
3. Ask Claude's LLM to generate the content (max 16000 tokens)
|
|
973
866
|
|
|
974
|
-
|
|
975
|
-
${selectedOption.advantages.slice(0, 3).map(a => `- ${a}`).join('\n')}
|
|
867
|
+
4. Write the generated content to `design-system/README.md`
|
|
976
868
|
|
|
977
|
-
**
|
|
978
|
-
- First Impression: [based on style name]
|
|
979
|
-
- During Use: [based on style name]
|
|
980
|
-
- Long-term: [based on style name]
|
|
869
|
+
**In current version (v2.0+), skip this step** - generation is split into STEP 5.5, 5.6, and 5.7
|
|
981
870
|
|
|
982
871
|
---
|
|
983
872
|
|
|
984
|
-
##
|
|
873
|
+
## STEP 5.5: Generate tokens.json and data.yaml (Enhanced v2.0.0)
|
|
985
874
|
|
|
986
|
-
|
|
875
|
+
> **Enhanced v2.0.0:** Now includes style, theme, animations, decorative_direction, and patterns_index
|
|
987
876
|
|
|
988
|
-
|
|
877
|
+
Display progress:
|
|
878
|
+
```
|
|
879
|
+
🔄 Generating enhanced tokens.json...
|
|
880
|
+
```
|
|
989
881
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
-
|
|
996
|
-
-
|
|
882
|
+
### Build Tokens Data Structure
|
|
883
|
+
|
|
884
|
+
Create a data structure with the following sections:
|
|
885
|
+
|
|
886
|
+
**1. Schema & Meta:**
|
|
887
|
+
- schema: "https://json-schema.org/draft-07/schema"
|
|
888
|
+
- version: "2.0.0"
|
|
889
|
+
- meta.generated_at: current timestamp (ISO format)
|
|
890
|
+
- meta.generated_by: "/designsetup command v2.0.0"
|
|
891
|
+
- meta.source_sites: list of extracted site names
|
|
892
|
+
- meta.description: "Design tokens for agents (~800 tokens). Human-readable guide: README.md"
|
|
893
|
+
|
|
894
|
+
**2. Style (from user selection in STEP 2):**
|
|
895
|
+
- style.name: selectedStyle.style
|
|
896
|
+
- style.confidence: selectedStyle.confidence
|
|
897
|
+
- style.characteristics: selectedStyle.characteristics
|
|
898
|
+
- style.feel: selectedStyle.feel
|
|
899
|
+
- style.source_site: selectedStyle.site
|
|
900
|
+
|
|
901
|
+
**3. Theme (from user selection in STEP 2.7):**
|
|
902
|
+
- theme.name: selectedTheme.name
|
|
903
|
+
- theme.description: selectedTheme.description
|
|
904
|
+
- theme.feeling: selectedTheme.feeling (or description if feeling not set)
|
|
905
|
+
- theme.decorative_elements.use: selectedTheme.decorative_elements
|
|
906
|
+
- theme.decorative_elements.avoid: selectedTheme.avoid_elements
|
|
907
|
+
- theme.icons_suggestion: selectedTheme.icons_suggestion (or ["Lucide icons"] as fallback)
|
|
908
|
+
|
|
909
|
+
**4. Animations (from user selection in STEP 2.6):**
|
|
910
|
+
- animations.enabled: true if selectedAnimations has items, false otherwise
|
|
911
|
+
- animations.libraries: extractedData[selectedStyle.site].animation_libraries (or empty array)
|
|
912
|
+
- animations.selected_patterns: selectedAnimations list
|
|
913
|
+
- animations.scroll_animations.enabled: true if any selected animation includes 'scroll', 'parallax', 'fade', or 'stacking'
|
|
914
|
+
- animations.scroll_animations.patterns: extractedData[selectedStyle.site].scroll_animations.patterns (or empty)
|
|
915
|
+
- animations.component_animations.button_hover: from selected site's data (or "scale + shadow" as fallback)
|
|
916
|
+
- animations.component_animations.card_hover: from selected site's data (or "translateY + shadow" as fallback)
|
|
917
|
+
- animations.component_animations.input_focus: from selected site's data (or "ring" as fallback)
|
|
918
|
+
- animations.duration.fast: "150ms"
|
|
919
|
+
- animations.duration.normal: "200ms"
|
|
920
|
+
- animations.duration.slow: "300ms"
|
|
921
|
+
- animations.easing.default: "ease-in-out"
|
|
922
|
+
- animations.easing.bounce: "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
|
|
923
|
+
|
|
924
|
+
**5. Colors (from selectedStyle):**
|
|
925
|
+
- colors.primary.DEFAULT: selectedStyle.colors[0] (or "#0d7276" as fallback)
|
|
926
|
+
- colors.primary.foreground: "#ffffff"
|
|
927
|
+
- colors.primary.hover: darken primary color by 10%
|
|
928
|
+
- colors.primary.tailwind: "bg-primary, text-primary, border-primary"
|
|
929
|
+
- colors.secondary.DEFAULT: selectedStyle.colors[1] (or "#64748b" as fallback)
|
|
930
|
+
- colors.secondary.foreground: "#ffffff"
|
|
931
|
+
- colors.secondary.hover: darken secondary color by 10%
|
|
932
|
+
- colors.accent.DEFAULT: selectedStyle.colors[2] (or primary color, or "#f97316")
|
|
933
|
+
- colors.accent.foreground: "#ffffff"
|
|
934
|
+
- colors.background: { DEFAULT: "#ffffff", muted: "#f1f5f9", subtle: "#f8fafc" }
|
|
935
|
+
- colors.foreground: { DEFAULT: "#0a0a0a", muted: "#64748b", subtle: "#94a3b8" }
|
|
936
|
+
- colors.border: { DEFAULT: "#e2e8f0", hover: "#cbd5e1", focus: primary color }
|
|
937
|
+
- colors.semantic: { success: "#10b981", warning: "#f59e0b", error: "#ef4444", info: "#3b82f6" }
|
|
938
|
+
|
|
939
|
+
**Color Darkening Logic:**
|
|
940
|
+
To darken a hex color by a percentage:
|
|
941
|
+
1. Remove '#' prefix and convert to integer
|
|
942
|
+
2. Calculate amount: round(2.55 * percent)
|
|
943
|
+
3. Extract RGB: R = (num >> 16), G = (num >> 8 & 0xFF), B = (num & 0xFF)
|
|
944
|
+
4. Subtract amount from each: max(R - amount, 0), max(G - amount, 0), max(B - amount, 0)
|
|
945
|
+
5. Recombine and convert back to hex with '#' prefix
|
|
946
|
+
|
|
947
|
+
**6. Typography (from selected site):**
|
|
948
|
+
- typography.font_family.sans: extractedData[selectedStyle.site].typography.fonts[0] (or "'Inter', sans-serif")
|
|
949
|
+
- typography.font_family.mono: "'Fira Code', monospace"
|
|
950
|
+
- typography.font_size: { xs: "12px", sm: "14px", base: "16px", lg: "18px", xl: "20px", 2xl: "24px", 3xl: "30px", 4xl: "36px", 5xl: "48px" }
|
|
951
|
+
- typography.font_weight: { normal: "400", medium: "500", semibold: "600", bold: "700" }
|
|
952
|
+
- typography.headings: { h1: "text-5xl font-bold", h2: "text-4xl font-bold", h3: "text-3xl font-semibold", h4: "text-2xl font-semibold", h5: "text-xl font-medium", h6: "text-lg font-medium" }
|
|
953
|
+
|
|
954
|
+
**7. Spacing (from selected site):**
|
|
955
|
+
- spacing.scale: extractedData[selectedStyle.site].spacing.common (or [4, 8, 12, 16, 24, 32, 48, 64, 96])
|
|
956
|
+
- spacing.grid_base: extractedData[selectedStyle.site].spacing.grid_base (or "8px")
|
|
957
|
+
- spacing.common_patterns: { component_padding: "p-4 (16px) or p-6 (24px)", section_gap: "gap-8 (32px) or gap-12 (48px)", layout_margin: "mt-16 (64px) or mt-24 (96px)" }
|
|
958
|
+
|
|
959
|
+
**8. Shadows (from selected site):**
|
|
960
|
+
- shadows.values: extractedData[selectedStyle.site].shadows (or default array)
|
|
961
|
+
- shadows.usage: { cards: "shadow-md", dropdowns: "shadow-lg", modals: "shadow-xl", buttons_hover: "shadow-sm" }
|
|
962
|
+
|
|
963
|
+
**9. Borders (from selected site):**
|
|
964
|
+
- borders.radius: extractedData[selectedStyle.site].border_radius (or ["4px", "8px", "12px", "9999px"])
|
|
965
|
+
- borders.usage: { inputs: "rounded-md", buttons: "rounded-lg", cards: "rounded-xl", avatars: "rounded-full" }
|
|
966
|
+
|
|
967
|
+
**10. Patterns Index:**
|
|
968
|
+
- patterns_index.buttons: "design-system/patterns/buttons.md"
|
|
969
|
+
- patterns_index.scroll_animations: "design-system/patterns/scroll-animations.md"
|
|
970
|
+
- patterns_index.decorations: "design-system/patterns/decorations.md"
|
|
971
|
+
- patterns_index.cards: "design-system/patterns/cards.md"
|
|
972
|
+
- patterns_index.forms: "design-system/patterns/forms.md"
|
|
973
|
+
|
|
974
|
+
**11. Component Library:**
|
|
975
|
+
- component_library.name: "shadcn/ui"
|
|
976
|
+
- component_library.install_command: "npx shadcn-ui@latest init"
|
|
977
|
+
- component_library.common_components: ["button", "card", "input", "select", "dialog", "dropdown-menu", "badge", "avatar", "tooltip"]
|
|
978
|
+
|
|
979
|
+
**12. Critical Rules:**
|
|
980
|
+
- critical_rules.colors: ["❌ NO hardcoded hex values", "✅ USE theme tokens (bg-primary, text-foreground)"]
|
|
981
|
+
- critical_rules.spacing: ["❌ NO arbitrary values (p-5, gap-7)", "✅ USE spacing scale (p-4, p-6, gap-8)"]
|
|
982
|
+
- critical_rules.consistency: ["❌ NO mixing patterns", "✅ USE consistent patterns from tokens"]
|
|
983
|
+
|
|
984
|
+
### Generate data.yaml
|
|
985
|
+
|
|
986
|
+
Call the helper function (see Helper section below) to generate YAML format with:
|
|
987
|
+
- Tokens data from above
|
|
988
|
+
- Psychology data from extractedData[selectedStyle.site]
|
|
989
|
+
- All design tokens in YAML format
|
|
990
|
+
|
|
991
|
+
Write to file: `design-system/data.yaml`
|
|
992
|
+
|
|
993
|
+
Display confirmation:
|
|
994
|
+
```
|
|
995
|
+
✅ data.yaml generated (~300 lines)
|
|
996
|
+
```
|
|
997
997
|
|
|
998
|
-
|
|
998
|
+
→ Continue to STEP 5.6
|
|
999
999
|
|
|
1000
1000
|
---
|
|
1001
1001
|
|
|
1002
|
-
##
|
|
1002
|
+
## STEP 5.6: Generate patterns/*.md Files
|
|
1003
1003
|
|
|
1004
|
-
|
|
1004
|
+
> **Code patterns for agents** - Selective loading based on page type
|
|
1005
1005
|
|
|
1006
|
-
|
|
1007
|
-
\`\`\`css
|
|
1008
|
-
font-family: [from ${selectedOption.sources.typography}]
|
|
1009
|
-
\`\`\`
|
|
1006
|
+
### STEP 5.6.1: Display Progress Message
|
|
1010
1007
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1008
|
+
Display progress message:
|
|
1009
|
+
```
|
|
1010
|
+
🔄 Generating pattern files...
|
|
1011
|
+
```
|
|
1013
1012
|
|
|
1014
|
-
|
|
1013
|
+
### STEP 5.6.2: Create Patterns Directory
|
|
1015
1014
|
|
|
1016
|
-
|
|
1015
|
+
Create the patterns directory:
|
|
1016
|
+
- Path: `design-system/patterns`
|
|
1017
1017
|
|
|
1018
|
-
|
|
1019
|
-
\`\`\`html
|
|
1020
|
-
<h1 className="[exact Tailwind classes from source]">
|
|
1021
|
-
Example Text
|
|
1022
|
-
</h1>
|
|
1023
|
-
\`\`\`
|
|
1024
|
-
- **Size**: [from source]
|
|
1025
|
-
- **Weight**: [from source]
|
|
1026
|
-
- **Source**: ${selectedOption.sources.typography}
|
|
1018
|
+
### STEP 5.6.3: Generate buttons.md
|
|
1027
1019
|
|
|
1028
|
-
|
|
1020
|
+
Build the buttons pattern content with these sections:
|
|
1029
1021
|
|
|
1030
|
-
|
|
1022
|
+
1. **Header metadata:**
|
|
1023
|
+
- Source: selectedStyle.site
|
|
1024
|
+
- Style: selectedStyle.style
|
|
1025
|
+
- Load when: "Any UI page"
|
|
1031
1026
|
|
|
1032
|
-
|
|
1027
|
+
2. **Button variants** (each with TSX code example):
|
|
1028
|
+
- Primary Button (with conditional hover based on tokensData.animations.component_animations.button_hover)
|
|
1029
|
+
- Secondary Button
|
|
1030
|
+
- Ghost Button
|
|
1031
|
+
- Outline Button
|
|
1032
|
+
- Icon Button
|
|
1033
1033
|
|
|
1034
|
-
|
|
1034
|
+
3. **Button sizes:**
|
|
1035
|
+
- Small: px-3 py-1.5 text-sm rounded-md
|
|
1036
|
+
- Medium (default): px-4 py-2 text-base rounded-lg
|
|
1037
|
+
- Large: px-6 py-3 text-lg rounded-lg
|
|
1035
1038
|
|
|
1036
|
-
|
|
1039
|
+
### STEP 5.6.4: Generate scroll-animations.md
|
|
1037
1040
|
|
|
1038
|
-
|
|
1041
|
+
Build the scroll animations pattern content with these sections:
|
|
1039
1042
|
|
|
1040
|
-
|
|
1043
|
+
1. **Header metadata:**
|
|
1044
|
+
- Source: selectedStyle.site
|
|
1045
|
+
- Style: selectedStyle.style
|
|
1046
|
+
- Load when: "Landing pages, marketing pages"
|
|
1047
|
+
- Libraries: List from tokensData.animations.libraries or "CSS/Tailwind"
|
|
1041
1048
|
|
|
1042
|
-
|
|
1049
|
+
2. **Enabled Patterns list:** List from selectedAnimations or "No scroll animations selected"
|
|
1043
1050
|
|
|
1044
|
-
|
|
1051
|
+
3. **Code examples** (TSX):
|
|
1052
|
+
- Fade In on Scroll (CSS with IntersectionObserver)
|
|
1053
|
+
- Stacking Cards (GSAP ScrollTrigger)
|
|
1054
|
+
- Parallax Section (CSS with scroll handler)
|
|
1055
|
+
- Slide In from Side (Left and Right animations)
|
|
1045
1056
|
|
|
1046
|
-
|
|
1047
|
-
\`\`\`tsx
|
|
1048
|
-
<button className="[exact classes from ${selectedOption.sources.button_hover}]">
|
|
1049
|
-
Click me
|
|
1050
|
-
</button>
|
|
1051
|
-
\`\`\`
|
|
1057
|
+
Write the content to `design-system/patterns/scroll-animations.md`
|
|
1052
1058
|
|
|
1053
|
-
|
|
1054
|
-
- **Type**: [from extracted animations]
|
|
1055
|
-
- **Description**: [from animations data]
|
|
1056
|
-
- **Source**: ${selectedOption.sources.button_hover}
|
|
1057
|
-
- **Duration**: [from source]
|
|
1059
|
+
### STEP 5.6.5: Generate decorations.md
|
|
1058
1060
|
|
|
1059
|
-
|
|
1061
|
+
Build the decorations pattern content with these sections:
|
|
1060
1062
|
|
|
1061
|
-
|
|
1063
|
+
1. **Header metadata:**
|
|
1064
|
+
- Theme: selectedTheme.name
|
|
1065
|
+
- Load when: "Landing pages, marketing pages (NOT dashboards)"
|
|
1062
1066
|
|
|
1063
|
-
|
|
1067
|
+
2. **Theme Direction:**
|
|
1068
|
+
- USE These Elements: List from selectedTheme.decorative_elements
|
|
1069
|
+
- AVOID These Elements: List from selectedTheme.avoid_elements or "(none specified)"
|
|
1070
|
+
- Suggested Icons (Lucide): List from selectedTheme.icons_suggestion or "Default Lucide icons"
|
|
1064
1071
|
|
|
1065
|
-
|
|
1072
|
+
3. **Code examples** (TSX):
|
|
1073
|
+
- Gradient Background (subtle overlay and mesh gradient)
|
|
1074
|
+
- Blob Shapes (animated blob with CSS keyframes)
|
|
1075
|
+
- Grid Pattern (dot grid and line grid backgrounds)
|
|
1076
|
+
- Floating Elements (floating icons with animation)
|
|
1077
|
+
- Dividers & Separators (wave divider SVG and gradient line)
|
|
1066
1078
|
|
|
1067
|
-
|
|
1079
|
+
Write the content to `design-system/patterns/decorations.md`
|
|
1068
1080
|
|
|
1069
|
-
|
|
1081
|
+
### STEP 5.6.6: Generate cards.md
|
|
1070
1082
|
|
|
1071
|
-
|
|
1083
|
+
Build the cards pattern content with these sections:
|
|
1072
1084
|
|
|
1073
|
-
|
|
1085
|
+
1. **Header metadata:**
|
|
1086
|
+
- Source: selectedStyle.site
|
|
1087
|
+
- Style: selectedStyle.style
|
|
1088
|
+
- Load when: "Any UI page"
|
|
1074
1089
|
|
|
1075
|
-
**
|
|
1076
|
-
-
|
|
1077
|
-
-
|
|
1078
|
-
-
|
|
1079
|
-
-
|
|
1090
|
+
2. **Card variants** (each with TSX code example):
|
|
1091
|
+
- Default Card
|
|
1092
|
+
- Interactive Card (with conditional hover based on tokensData.animations.component_animations.card_hover)
|
|
1093
|
+
- Feature Card (with icon container)
|
|
1094
|
+
- Pricing Card (with popular badge, price, features list, CTA button)
|
|
1095
|
+
- Testimonial Card (with avatar, name, title, quote)
|
|
1080
1096
|
|
|
1081
|
-
|
|
1097
|
+
Write the content to `design-system/patterns/cards.md`
|
|
1082
1098
|
|
|
1083
|
-
|
|
1099
|
+
### STEP 5.6.7: Generate forms.md
|
|
1084
1100
|
|
|
1085
|
-
|
|
1101
|
+
Build the forms pattern content with these sections:
|
|
1086
1102
|
|
|
1087
|
-
**
|
|
1088
|
-
|
|
1103
|
+
1. **Header metadata:**
|
|
1104
|
+
- Source: selectedStyle.site
|
|
1105
|
+
- Style: selectedStyle.style
|
|
1106
|
+
- Load when: "Auth pages, settings, any form UI"
|
|
1089
1107
|
|
|
1090
|
-
**
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1108
|
+
2. **Form elements** (each with TSX code example):
|
|
1109
|
+
- Input Field (with label, input, helper text)
|
|
1110
|
+
- Input with Error (error state styling and error message)
|
|
1111
|
+
- Select Field (dropdown)
|
|
1112
|
+
- Checkbox (with label)
|
|
1113
|
+
- Form Layout (complete form with submit button)
|
|
1094
1114
|
|
|
1095
|
-
|
|
1096
|
-
*Date: ${new Date().toISOString().split('T')[0]}*
|
|
1097
|
-
*Sources: ${Object.keys(extractedData).join(', ')}*
|
|
1098
|
-
`;
|
|
1115
|
+
Write the content to `design-system/patterns/forms.md`
|
|
1099
1116
|
|
|
1100
|
-
|
|
1101
|
-
prompt: styleGuidePrompt,
|
|
1102
|
-
max_tokens: 16000
|
|
1103
|
-
});
|
|
1117
|
+
### STEP 5.6.8: Display Completion Message
|
|
1104
1118
|
|
|
1105
|
-
|
|
1119
|
+
Display completion message:
|
|
1106
1120
|
```
|
|
1107
|
-
|
|
1108
|
-
---
|
|
1109
|
-
|
|
1110
|
-
## STEP 5.5: Generate tokens.json (Enhanced v2.0.0)
|
|
1111
|
-
|
|
1112
|
-
> **Enhanced v2.0.0:** tokens.json now includes style, theme, animations, decorative_direction, and patterns_index
|
|
1113
|
-
|
|
1114
|
-
```javascript
|
|
1115
|
-
output(`
|
|
1116
|
-
🔄 Generating enhanced tokens.json...
|
|
1117
|
-
`);
|
|
1118
|
-
|
|
1119
|
-
// Build tokens.json from user selections + extracted data
|
|
1120
|
-
const tokensData = {
|
|
1121
|
-
"$schema": "https://json-schema.org/draft-07/schema",
|
|
1122
|
-
"version": "2.0.0",
|
|
1123
|
-
"meta": {
|
|
1124
|
-
"generated_at": new Date().toISOString(),
|
|
1125
|
-
"generated_by": "/designsetup command v2.0.0",
|
|
1126
|
-
"source_sites": Object.keys(extractedData),
|
|
1127
|
-
"description": "Design tokens for agents (~800 tokens). Human-readable guide: README.md"
|
|
1128
|
-
},
|
|
1129
|
-
|
|
1130
|
-
// ========== NEW: Style & Theme (from user selection) ==========
|
|
1131
|
-
"style": {
|
|
1132
|
-
"name": selectedStyle.style,
|
|
1133
|
-
"confidence": selectedStyle.confidence,
|
|
1134
|
-
"characteristics": selectedStyle.characteristics,
|
|
1135
|
-
"feel": selectedStyle.feel,
|
|
1136
|
-
"source_site": selectedStyle.site
|
|
1137
|
-
},
|
|
1138
|
-
|
|
1139
|
-
"theme": {
|
|
1140
|
-
"name": selectedTheme.name,
|
|
1141
|
-
"description": selectedTheme.description,
|
|
1142
|
-
"feeling": selectedTheme.feeling || selectedTheme.description,
|
|
1143
|
-
"decorative_elements": {
|
|
1144
|
-
"use": selectedTheme.decorative_elements,
|
|
1145
|
-
"avoid": selectedTheme.avoid_elements
|
|
1146
|
-
},
|
|
1147
|
-
"icons_suggestion": selectedTheme.icons_suggestion || ["Lucide icons"]
|
|
1148
|
-
},
|
|
1149
|
-
|
|
1150
|
-
// ========== NEW: Animations (from user selection) ==========
|
|
1151
|
-
"animations": {
|
|
1152
|
-
"enabled": selectedAnimations.length > 0,
|
|
1153
|
-
"libraries": extractedData[selectedStyle.site]?.animation_libraries || [],
|
|
1154
|
-
"selected_patterns": selectedAnimations,
|
|
1155
|
-
"scroll_animations": {
|
|
1156
|
-
"enabled": selectedAnimations.some(a =>
|
|
1157
|
-
a.includes('scroll') || a.includes('parallax') || a.includes('fade') || a.includes('stacking')
|
|
1158
|
-
),
|
|
1159
|
-
"patterns": extractedData[selectedStyle.site]?.scroll_animations?.patterns || []
|
|
1160
|
-
},
|
|
1161
|
-
"component_animations": {
|
|
1162
|
-
"button_hover": extractedData[selectedStyle.site]?.component_animations?.button_hover || "scale + shadow",
|
|
1163
|
-
"card_hover": extractedData[selectedStyle.site]?.component_animations?.card_hover || "translateY + shadow",
|
|
1164
|
-
"input_focus": extractedData[selectedStyle.site]?.component_animations?.input_focus || "ring"
|
|
1165
|
-
},
|
|
1166
|
-
"duration": {
|
|
1167
|
-
"fast": "150ms",
|
|
1168
|
-
"normal": "200ms",
|
|
1169
|
-
"slow": "300ms"
|
|
1170
|
-
},
|
|
1171
|
-
"easing": {
|
|
1172
|
-
"default": "ease-in-out",
|
|
1173
|
-
"bounce": "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
|
|
1174
|
-
}
|
|
1175
|
-
},
|
|
1176
|
-
|
|
1177
|
-
// ========== Colors (from selected style's source) ==========
|
|
1178
|
-
"colors": {
|
|
1179
|
-
"primary": {
|
|
1180
|
-
"DEFAULT": selectedStyle.colors[0] || "#0d7276",
|
|
1181
|
-
"foreground": "#ffffff",
|
|
1182
|
-
"hover": darkenColor(selectedStyle.colors[0] || "#0d7276", 10),
|
|
1183
|
-
"tailwind": "bg-primary, text-primary, border-primary"
|
|
1184
|
-
},
|
|
1185
|
-
"secondary": {
|
|
1186
|
-
"DEFAULT": selectedStyle.colors[1] || "#64748b",
|
|
1187
|
-
"foreground": "#ffffff",
|
|
1188
|
-
"hover": darkenColor(selectedStyle.colors[1] || "#64748b", 10)
|
|
1189
|
-
},
|
|
1190
|
-
"accent": {
|
|
1191
|
-
"DEFAULT": selectedStyle.colors[2] || selectedStyle.colors[0] || "#f97316",
|
|
1192
|
-
"foreground": "#ffffff"
|
|
1193
|
-
},
|
|
1194
|
-
"background": {
|
|
1195
|
-
"DEFAULT": "#ffffff",
|
|
1196
|
-
"muted": "#f1f5f9",
|
|
1197
|
-
"subtle": "#f8fafc"
|
|
1198
|
-
},
|
|
1199
|
-
"foreground": {
|
|
1200
|
-
"DEFAULT": "#0a0a0a",
|
|
1201
|
-
"muted": "#64748b",
|
|
1202
|
-
"subtle": "#94a3b8"
|
|
1203
|
-
},
|
|
1204
|
-
"border": {
|
|
1205
|
-
"DEFAULT": "#e2e8f0",
|
|
1206
|
-
"hover": "#cbd5e1",
|
|
1207
|
-
"focus": selectedStyle.colors[0] || "#0d7276"
|
|
1208
|
-
},
|
|
1209
|
-
"semantic": {
|
|
1210
|
-
"success": "#10b981",
|
|
1211
|
-
"warning": "#f59e0b",
|
|
1212
|
-
"error": "#ef4444",
|
|
1213
|
-
"info": "#3b82f6"
|
|
1214
|
-
}
|
|
1215
|
-
},
|
|
1216
|
-
|
|
1217
|
-
// ========== Typography (from extracted data) ==========
|
|
1218
|
-
"typography": {
|
|
1219
|
-
"font_family": {
|
|
1220
|
-
"sans": extractedData[selectedStyle.site]?.typography?.fonts[0] || "'Inter', sans-serif",
|
|
1221
|
-
"mono": "'Fira Code', monospace"
|
|
1222
|
-
},
|
|
1223
|
-
"font_size": {
|
|
1224
|
-
"xs": "12px", "sm": "14px", "base": "16px", "lg": "18px",
|
|
1225
|
-
"xl": "20px", "2xl": "24px", "3xl": "30px", "4xl": "36px", "5xl": "48px"
|
|
1226
|
-
},
|
|
1227
|
-
"font_weight": {
|
|
1228
|
-
"normal": "400", "medium": "500", "semibold": "600", "bold": "700"
|
|
1229
|
-
},
|
|
1230
|
-
"headings": {
|
|
1231
|
-
"h1": "text-5xl font-bold",
|
|
1232
|
-
"h2": "text-4xl font-bold",
|
|
1233
|
-
"h3": "text-3xl font-semibold",
|
|
1234
|
-
"h4": "text-2xl font-semibold",
|
|
1235
|
-
"h5": "text-xl font-medium",
|
|
1236
|
-
"h6": "text-lg font-medium"
|
|
1237
|
-
}
|
|
1238
|
-
},
|
|
1239
|
-
|
|
1240
|
-
// ========== Spacing (from extracted data) ==========
|
|
1241
|
-
"spacing": {
|
|
1242
|
-
"scale": extractedData[selectedStyle.site]?.spacing?.common || [4, 8, 12, 16, 24, 32, 48, 64, 96],
|
|
1243
|
-
"grid_base": extractedData[selectedStyle.site]?.spacing?.grid_base || "8px",
|
|
1244
|
-
"common_patterns": {
|
|
1245
|
-
"component_padding": "p-4 (16px) or p-6 (24px)",
|
|
1246
|
-
"section_gap": "gap-8 (32px) or gap-12 (48px)",
|
|
1247
|
-
"layout_margin": "mt-16 (64px) or mt-24 (96px)"
|
|
1248
|
-
}
|
|
1249
|
-
},
|
|
1250
|
-
|
|
1251
|
-
// ========== Shadows (from extracted data) ==========
|
|
1252
|
-
"shadows": {
|
|
1253
|
-
"values": extractedData[selectedStyle.site]?.shadows || [
|
|
1254
|
-
"0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
1255
|
-
"0 4px 6px -1px rgb(0 0 0 / 0.1)",
|
|
1256
|
-
"0 10px 15px -3px rgb(0 0 0 / 0.1)"
|
|
1257
|
-
],
|
|
1258
|
-
"usage": {
|
|
1259
|
-
"cards": "shadow-md",
|
|
1260
|
-
"dropdowns": "shadow-lg",
|
|
1261
|
-
"modals": "shadow-xl",
|
|
1262
|
-
"buttons_hover": "shadow-sm"
|
|
1263
|
-
}
|
|
1264
|
-
},
|
|
1265
|
-
|
|
1266
|
-
// ========== Borders (from extracted data) ==========
|
|
1267
|
-
"borders": {
|
|
1268
|
-
"radius": extractedData[selectedStyle.site]?.border_radius || ["4px", "8px", "12px", "9999px"],
|
|
1269
|
-
"usage": {
|
|
1270
|
-
"inputs": "rounded-md",
|
|
1271
|
-
"buttons": "rounded-lg",
|
|
1272
|
-
"cards": "rounded-xl",
|
|
1273
|
-
"avatars": "rounded-full"
|
|
1274
|
-
}
|
|
1275
|
-
},
|
|
1276
|
-
|
|
1277
|
-
// ========== NEW: Patterns Index (references to patterns/*.md) ==========
|
|
1278
|
-
"patterns_index": {
|
|
1279
|
-
"buttons": "design-system/patterns/buttons.md",
|
|
1280
|
-
"scroll_animations": "design-system/patterns/scroll-animations.md",
|
|
1281
|
-
"decorations": "design-system/patterns/decorations.md",
|
|
1282
|
-
"cards": "design-system/patterns/cards.md",
|
|
1283
|
-
"forms": "design-system/patterns/forms.md"
|
|
1284
|
-
},
|
|
1285
|
-
|
|
1286
|
-
// ========== Component Library ==========
|
|
1287
|
-
"component_library": {
|
|
1288
|
-
"name": "shadcn/ui",
|
|
1289
|
-
"install_command": "npx shadcn-ui@latest init",
|
|
1290
|
-
"common_components": ["button", "card", "input", "select", "dialog", "dropdown-menu", "badge", "avatar", "tooltip"]
|
|
1291
|
-
},
|
|
1292
|
-
|
|
1293
|
-
// ========== Critical Rules ==========
|
|
1294
|
-
"critical_rules": {
|
|
1295
|
-
"colors": [
|
|
1296
|
-
"❌ NO hardcoded hex values",
|
|
1297
|
-
"✅ USE theme tokens (bg-primary, text-foreground)"
|
|
1298
|
-
],
|
|
1299
|
-
"spacing": [
|
|
1300
|
-
"❌ NO arbitrary values (p-5, gap-7)",
|
|
1301
|
-
"✅ USE spacing scale (p-4, p-6, gap-8)"
|
|
1302
|
-
],
|
|
1303
|
-
"consistency": [
|
|
1304
|
-
"❌ NO mixing patterns",
|
|
1305
|
-
"✅ USE consistent patterns from tokens"
|
|
1306
|
-
]
|
|
1307
|
-
}
|
|
1308
|
-
};
|
|
1309
|
-
|
|
1310
|
-
// Helper function to darken color
|
|
1311
|
-
function darkenColor(hex, percent) {
|
|
1312
|
-
const num = parseInt(hex.replace('#', ''), 16);
|
|
1313
|
-
const amt = Math.round(2.55 * percent);
|
|
1314
|
-
const R = Math.max((num >> 16) - amt, 0);
|
|
1315
|
-
const G = Math.max((num >> 8 & 0x00FF) - amt, 0);
|
|
1316
|
-
const B = Math.max((num & 0x0000FF) - amt, 0);
|
|
1317
|
-
return '#' + (0x1000000 + R * 0x10000 + G * 0x100 + B).toString(16).slice(1);
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
// Write data.yaml (includes psychology from extracted sites)
|
|
1321
|
-
const dataYaml = generateDataYaml(tokensData, extractedData, selectedStyle);
|
|
1322
|
-
Write('design-system/data.yaml', dataYaml);
|
|
1323
|
-
output(`✅ data.yaml generated (~300 lines)`);
|
|
1324
|
-
```
|
|
1325
|
-
|
|
1326
|
-
---
|
|
1327
|
-
|
|
1328
|
-
## STEP 5.6: Generate patterns/*.md Files
|
|
1329
|
-
|
|
1330
|
-
> **Code patterns for agents** - Selective loading based on page type
|
|
1331
|
-
|
|
1332
|
-
```javascript
|
|
1333
|
-
output(`
|
|
1334
|
-
🔄 Generating pattern files...
|
|
1335
|
-
`);
|
|
1336
|
-
|
|
1337
|
-
// Create patterns directory
|
|
1338
|
-
mkdir('design-system/patterns');
|
|
1339
|
-
|
|
1340
|
-
// ========== 1. buttons.md ==========
|
|
1341
|
-
const buttonsPattern = `# Button Patterns
|
|
1342
|
-
|
|
1343
|
-
> **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
|
|
1344
|
-
> **Load when:** Any UI page
|
|
1345
|
-
|
|
1346
|
-
## Primary Button
|
|
1347
|
-
\`\`\`tsx
|
|
1348
|
-
<button className="
|
|
1349
|
-
bg-primary text-primary-foreground
|
|
1350
|
-
px-4 py-2 rounded-lg
|
|
1351
|
-
font-medium
|
|
1352
|
-
${tokensData.animations.component_animations.button_hover === 'scale + shadow'
|
|
1353
|
-
? 'hover:scale-105 hover:shadow-md'
|
|
1354
|
-
: 'hover:bg-primary/90'}
|
|
1355
|
-
transition-all duration-200
|
|
1356
|
-
focus:outline-none focus:ring-2 focus:ring-primary/50
|
|
1357
|
-
disabled:opacity-50 disabled:cursor-not-allowed
|
|
1358
|
-
">
|
|
1359
|
-
Button Text
|
|
1360
|
-
</button>
|
|
1361
|
-
\`\`\`
|
|
1362
|
-
|
|
1363
|
-
## Secondary Button
|
|
1364
|
-
\`\`\`tsx
|
|
1365
|
-
<button className="
|
|
1366
|
-
bg-secondary text-secondary-foreground
|
|
1367
|
-
px-4 py-2 rounded-lg
|
|
1368
|
-
font-medium
|
|
1369
|
-
hover:bg-secondary/80
|
|
1370
|
-
transition-all duration-200
|
|
1371
|
-
">
|
|
1372
|
-
Secondary
|
|
1373
|
-
</button>
|
|
1374
|
-
\`\`\`
|
|
1375
|
-
|
|
1376
|
-
## Ghost Button
|
|
1377
|
-
\`\`\`tsx
|
|
1378
|
-
<button className="
|
|
1379
|
-
bg-transparent text-foreground
|
|
1380
|
-
px-4 py-2 rounded-lg
|
|
1381
|
-
font-medium
|
|
1382
|
-
hover:bg-muted
|
|
1383
|
-
transition-all duration-200
|
|
1384
|
-
">
|
|
1385
|
-
Ghost
|
|
1386
|
-
</button>
|
|
1387
|
-
\`\`\`
|
|
1388
|
-
|
|
1389
|
-
## Outline Button
|
|
1390
|
-
\`\`\`tsx
|
|
1391
|
-
<button className="
|
|
1392
|
-
bg-transparent text-primary
|
|
1393
|
-
border border-primary
|
|
1394
|
-
px-4 py-2 rounded-lg
|
|
1395
|
-
font-medium
|
|
1396
|
-
hover:bg-primary hover:text-primary-foreground
|
|
1397
|
-
transition-all duration-200
|
|
1398
|
-
">
|
|
1399
|
-
Outline
|
|
1400
|
-
</button>
|
|
1401
|
-
\`\`\`
|
|
1402
|
-
|
|
1403
|
-
## Icon Button
|
|
1404
|
-
\`\`\`tsx
|
|
1405
|
-
<button className="
|
|
1406
|
-
p-2 rounded-lg
|
|
1407
|
-
hover:bg-muted
|
|
1408
|
-
transition-all duration-200
|
|
1409
|
-
">
|
|
1410
|
-
<Icon className="w-5 h-5" />
|
|
1411
|
-
</button>
|
|
1412
|
-
\`\`\`
|
|
1413
|
-
|
|
1414
|
-
## Button Sizes
|
|
1415
|
-
\`\`\`tsx
|
|
1416
|
-
// Small
|
|
1417
|
-
className="px-3 py-1.5 text-sm rounded-md"
|
|
1418
|
-
|
|
1419
|
-
// Medium (default)
|
|
1420
|
-
className="px-4 py-2 text-base rounded-lg"
|
|
1421
|
-
|
|
1422
|
-
// Large
|
|
1423
|
-
className="px-6 py-3 text-lg rounded-lg"
|
|
1424
|
-
\`\`\`
|
|
1425
|
-
`;
|
|
1426
|
-
|
|
1427
|
-
Write('design-system/patterns/buttons.md', buttonsPattern);
|
|
1428
|
-
|
|
1429
|
-
// ========== 2. scroll-animations.md ==========
|
|
1430
|
-
const scrollAnimationsPattern = `# Scroll Animation Patterns
|
|
1431
|
-
|
|
1432
|
-
> **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
|
|
1433
|
-
> **Load when:** Landing pages, marketing pages
|
|
1434
|
-
> **Libraries:** ${tokensData.animations.libraries.map(l => l.name).join(', ') || 'CSS/Tailwind'}
|
|
1435
|
-
|
|
1436
|
-
## Enabled Patterns
|
|
1437
|
-
${selectedAnimations.length > 0 ? selectedAnimations.map(a => `- ${a}`).join('\n') : '- No scroll animations selected'}
|
|
1438
|
-
|
|
1439
|
-
---
|
|
1440
|
-
|
|
1441
|
-
## Fade In on Scroll (CSS)
|
|
1442
|
-
\`\`\`tsx
|
|
1443
|
-
// Add to component
|
|
1444
|
-
const [isVisible, setIsVisible] = useState(false);
|
|
1445
|
-
const ref = useRef(null);
|
|
1446
|
-
|
|
1447
|
-
useEffect(() => {
|
|
1448
|
-
const observer = new IntersectionObserver(
|
|
1449
|
-
([entry]) => setIsVisible(entry.isIntersecting),
|
|
1450
|
-
{ threshold: 0.1 }
|
|
1451
|
-
);
|
|
1452
|
-
if (ref.current) observer.observe(ref.current);
|
|
1453
|
-
return () => observer.disconnect();
|
|
1454
|
-
}, []);
|
|
1455
|
-
|
|
1456
|
-
return (
|
|
1457
|
-
<div
|
|
1458
|
-
ref={ref}
|
|
1459
|
-
className={\`
|
|
1460
|
-
transition-all duration-700
|
|
1461
|
-
\${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}
|
|
1462
|
-
\`}
|
|
1463
|
-
>
|
|
1464
|
-
{children}
|
|
1465
|
-
</div>
|
|
1466
|
-
);
|
|
1467
|
-
\`\`\`
|
|
1468
|
-
|
|
1469
|
-
## Stacking Cards (GSAP ScrollTrigger)
|
|
1470
|
-
\`\`\`tsx
|
|
1471
|
-
// Requires: npm install gsap
|
|
1472
|
-
|
|
1473
|
-
import { gsap } from 'gsap';
|
|
1474
|
-
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
1475
|
-
|
|
1476
|
-
gsap.registerPlugin(ScrollTrigger);
|
|
1477
|
-
|
|
1478
|
-
useEffect(() => {
|
|
1479
|
-
const cards = gsap.utils.toArray('.stacking-card');
|
|
1480
|
-
|
|
1481
|
-
cards.forEach((card, i) => {
|
|
1482
|
-
gsap.to(card, {
|
|
1483
|
-
scrollTrigger: {
|
|
1484
|
-
trigger: card,
|
|
1485
|
-
start: 'top 80%',
|
|
1486
|
-
end: 'top 20%',
|
|
1487
|
-
scrub: true,
|
|
1488
|
-
},
|
|
1489
|
-
y: -50 * i,
|
|
1490
|
-
scale: 1 - (0.05 * i),
|
|
1491
|
-
opacity: 1 - (0.1 * i),
|
|
1492
|
-
});
|
|
1493
|
-
});
|
|
1494
|
-
}, []);
|
|
1495
|
-
|
|
1496
|
-
// JSX
|
|
1497
|
-
<div className="stacking-card bg-card p-6 rounded-xl shadow-md sticky top-20">
|
|
1498
|
-
Card Content
|
|
1499
|
-
</div>
|
|
1500
|
-
\`\`\`
|
|
1501
|
-
|
|
1502
|
-
## Parallax Section
|
|
1503
|
-
\`\`\`tsx
|
|
1504
|
-
// CSS approach
|
|
1505
|
-
<div className="relative overflow-hidden">
|
|
1506
|
-
<div
|
|
1507
|
-
className="absolute inset-0 bg-cover bg-center"
|
|
1508
|
-
style={{
|
|
1509
|
-
backgroundImage: 'url(/hero-bg.jpg)',
|
|
1510
|
-
transform: 'translateY(var(--parallax-offset, 0))',
|
|
1511
|
-
}}
|
|
1512
|
-
/>
|
|
1513
|
-
<div className="relative z-10 py-24">
|
|
1514
|
-
Content here
|
|
1515
|
-
</div>
|
|
1516
|
-
</div>
|
|
1517
|
-
|
|
1518
|
-
// Update --parallax-offset on scroll
|
|
1519
|
-
useEffect(() => {
|
|
1520
|
-
const handleScroll = () => {
|
|
1521
|
-
const offset = window.scrollY * 0.5;
|
|
1522
|
-
document.documentElement.style.setProperty('--parallax-offset', \`\${offset}px\`);
|
|
1523
|
-
};
|
|
1524
|
-
window.addEventListener('scroll', handleScroll);
|
|
1525
|
-
return () => window.removeEventListener('scroll', handleScroll);
|
|
1526
|
-
}, []);
|
|
1527
|
-
\`\`\`
|
|
1528
|
-
|
|
1529
|
-
## Slide In from Side
|
|
1530
|
-
\`\`\`tsx
|
|
1531
|
-
// Left
|
|
1532
|
-
className="animate-slide-in-left"
|
|
1533
|
-
// CSS: @keyframes slide-in-left { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
|
|
1534
|
-
|
|
1535
|
-
// Right
|
|
1536
|
-
className="animate-slide-in-right"
|
|
1537
|
-
// CSS: @keyframes slide-in-right { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
|
|
1538
|
-
\`\`\`
|
|
1539
|
-
`;
|
|
1540
|
-
|
|
1541
|
-
Write('design-system/patterns/scroll-animations.md', scrollAnimationsPattern);
|
|
1542
|
-
|
|
1543
|
-
// ========== 3. decorations.md ==========
|
|
1544
|
-
const decorationsPattern = `# Decorative Elements
|
|
1545
|
-
|
|
1546
|
-
> **Theme:** ${selectedTheme.name}
|
|
1547
|
-
> **Load when:** Landing pages, marketing pages (NOT dashboards)
|
|
1548
|
-
|
|
1549
|
-
## Theme Direction
|
|
1550
|
-
|
|
1551
|
-
### ✅ USE These Elements
|
|
1552
|
-
${selectedTheme.decorative_elements.map(e => `- ${e}`).join('\n')}
|
|
1553
|
-
|
|
1554
|
-
### ❌ AVOID These Elements
|
|
1555
|
-
${selectedTheme.avoid_elements.length > 0 ? selectedTheme.avoid_elements.map(e => `- ${e}`).join('\n') : '- (none specified)'}
|
|
1556
|
-
|
|
1557
|
-
### 🎯 Suggested Icons (Lucide)
|
|
1558
|
-
${selectedTheme.icons_suggestion?.join(', ') || 'Default Lucide icons'}
|
|
1559
|
-
|
|
1560
|
-
---
|
|
1561
|
-
|
|
1562
|
-
## Gradient Background
|
|
1563
|
-
\`\`\`tsx
|
|
1564
|
-
// Subtle gradient overlay
|
|
1565
|
-
<div className="
|
|
1566
|
-
absolute inset-0 -z-10
|
|
1567
|
-
bg-gradient-to-br from-primary/5 via-transparent to-accent/5
|
|
1568
|
-
"/>
|
|
1569
|
-
|
|
1570
|
-
// Mesh gradient (hero sections)
|
|
1571
|
-
<div className="
|
|
1572
|
-
absolute inset-0 -z-10
|
|
1573
|
-
bg-[radial-gradient(ellipse_80%_80%_at_50%_-20%,rgba(var(--primary),0.3),transparent)]
|
|
1574
|
-
"/>
|
|
1575
|
-
\`\`\`
|
|
1576
|
-
|
|
1577
|
-
## Blob Shapes
|
|
1578
|
-
\`\`\`tsx
|
|
1579
|
-
// CSS blob
|
|
1580
|
-
<div className="
|
|
1581
|
-
absolute -top-20 -right-20 w-96 h-96
|
|
1582
|
-
bg-primary/10 rounded-full blur-3xl
|
|
1583
|
-
animate-blob
|
|
1584
|
-
"/>
|
|
1585
|
-
|
|
1586
|
-
// CSS for animation
|
|
1587
|
-
// @keyframes blob {
|
|
1588
|
-
// 0%, 100% { transform: translate(0, 0) scale(1); }
|
|
1589
|
-
// 33% { transform: translate(30px, -50px) scale(1.1); }
|
|
1590
|
-
// 66% { transform: translate(-20px, 20px) scale(0.9); }
|
|
1591
|
-
// }
|
|
1592
|
-
\`\`\`
|
|
1593
|
-
|
|
1594
|
-
## Grid Pattern
|
|
1595
|
-
\`\`\`tsx
|
|
1596
|
-
// Dot grid background
|
|
1597
|
-
<div className="
|
|
1598
|
-
absolute inset-0 -z-10
|
|
1599
|
-
bg-[radial-gradient(#e5e7eb_1px,transparent_1px)]
|
|
1600
|
-
[background-size:16px_16px]
|
|
1601
|
-
"/>
|
|
1602
|
-
|
|
1603
|
-
// Line grid
|
|
1604
|
-
<div className="
|
|
1605
|
-
absolute inset-0 -z-10
|
|
1606
|
-
bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)]
|
|
1607
|
-
[background-size:24px_24px]
|
|
1608
|
-
"/>
|
|
1609
|
-
\`\`\`
|
|
1610
|
-
|
|
1611
|
-
## Floating Elements
|
|
1612
|
-
\`\`\`tsx
|
|
1613
|
-
// Floating icons (for theme: ${selectedTheme.name})
|
|
1614
|
-
<div className="absolute top-10 left-10 animate-float opacity-20">
|
|
1615
|
-
<IconFromTheme className="w-12 h-12 text-primary" />
|
|
1616
|
-
</div>
|
|
1617
|
-
|
|
1618
|
-
// CSS
|
|
1619
|
-
// @keyframes float {
|
|
1620
|
-
// 0%, 100% { transform: translateY(0); }
|
|
1621
|
-
// 50% { transform: translateY(-20px); }
|
|
1622
|
-
// }
|
|
1623
|
-
\`\`\`
|
|
1624
|
-
|
|
1625
|
-
## Dividers & Separators
|
|
1626
|
-
\`\`\`tsx
|
|
1627
|
-
// Wave divider
|
|
1628
|
-
<svg className="w-full h-16" viewBox="0 0 1200 120" preserveAspectRatio="none">
|
|
1629
|
-
<path d="M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z" fill="currentColor" className="text-muted/30"/>
|
|
1630
|
-
</svg>
|
|
1631
|
-
|
|
1632
|
-
// Gradient line
|
|
1633
|
-
<div className="h-px bg-gradient-to-r from-transparent via-border to-transparent" />
|
|
1634
|
-
\`\`\`
|
|
1635
|
-
`;
|
|
1636
|
-
|
|
1637
|
-
Write('design-system/patterns/decorations.md', decorationsPattern);
|
|
1638
|
-
|
|
1639
|
-
// ========== 4. cards.md ==========
|
|
1640
|
-
const cardsPattern = `# Card Patterns
|
|
1641
|
-
|
|
1642
|
-
> **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
|
|
1643
|
-
> **Load when:** Any UI page
|
|
1644
|
-
|
|
1645
|
-
## Default Card
|
|
1646
|
-
\`\`\`tsx
|
|
1647
|
-
<div className="
|
|
1648
|
-
bg-card text-card-foreground
|
|
1649
|
-
rounded-xl border shadow-md
|
|
1650
|
-
p-6
|
|
1651
|
-
">
|
|
1652
|
-
<h3 className="text-xl font-semibold mb-2">Card Title</h3>
|
|
1653
|
-
<p className="text-muted-foreground">Card content goes here.</p>
|
|
1654
|
-
</div>
|
|
1655
|
-
\`\`\`
|
|
1656
|
-
|
|
1657
|
-
## Interactive Card (with hover)
|
|
1658
|
-
\`\`\`tsx
|
|
1659
|
-
<div className="
|
|
1660
|
-
bg-card text-card-foreground
|
|
1661
|
-
rounded-xl border shadow-md
|
|
1662
|
-
p-6
|
|
1663
|
-
${tokensData.animations.component_animations.card_hover === 'translateY + shadow'
|
|
1664
|
-
? 'hover:-translate-y-1 hover:shadow-lg'
|
|
1665
|
-
: 'hover:border-primary/50'}
|
|
1666
|
-
transition-all duration-200
|
|
1667
|
-
cursor-pointer
|
|
1668
|
-
">
|
|
1669
|
-
<h3 className="text-xl font-semibold mb-2">Interactive Card</h3>
|
|
1670
|
-
<p className="text-muted-foreground">Hover me!</p>
|
|
1671
|
-
</div>
|
|
1672
|
-
\`\`\`
|
|
1673
|
-
|
|
1674
|
-
## Feature Card
|
|
1675
|
-
\`\`\`tsx
|
|
1676
|
-
<div className="
|
|
1677
|
-
bg-card text-card-foreground
|
|
1678
|
-
rounded-xl border shadow-md
|
|
1679
|
-
p-6
|
|
1680
|
-
hover:-translate-y-1 hover:shadow-lg
|
|
1681
|
-
transition-all duration-200
|
|
1682
|
-
">
|
|
1683
|
-
<div className="w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center mb-4">
|
|
1684
|
-
<Icon className="w-6 h-6 text-primary" />
|
|
1685
|
-
</div>
|
|
1686
|
-
<h3 className="text-lg font-semibold mb-2">Feature Title</h3>
|
|
1687
|
-
<p className="text-muted-foreground text-sm">
|
|
1688
|
-
Feature description goes here.
|
|
1689
|
-
</p>
|
|
1690
|
-
</div>
|
|
1691
|
-
\`\`\`
|
|
1692
|
-
|
|
1693
|
-
## Pricing Card
|
|
1694
|
-
\`\`\`tsx
|
|
1695
|
-
<div className="
|
|
1696
|
-
bg-card text-card-foreground
|
|
1697
|
-
rounded-xl border shadow-md
|
|
1698
|
-
p-8
|
|
1699
|
-
relative overflow-hidden
|
|
1700
|
-
">
|
|
1701
|
-
{/* Popular badge */}
|
|
1702
|
-
<div className="absolute top-4 right-4">
|
|
1703
|
-
<span className="bg-primary text-primary-foreground px-3 py-1 rounded-full text-xs font-medium">
|
|
1704
|
-
Popular
|
|
1705
|
-
</span>
|
|
1706
|
-
</div>
|
|
1707
|
-
|
|
1708
|
-
<h3 className="text-xl font-bold mb-2">Pro Plan</h3>
|
|
1709
|
-
<div className="text-4xl font-bold mb-4">
|
|
1710
|
-
$29<span className="text-lg text-muted-foreground">/mo</span>
|
|
1711
|
-
</div>
|
|
1712
|
-
|
|
1713
|
-
<ul className="space-y-3 mb-6">
|
|
1714
|
-
<li className="flex items-center gap-2">
|
|
1715
|
-
<CheckIcon className="w-5 h-5 text-primary" />
|
|
1716
|
-
<span>Feature 1</span>
|
|
1717
|
-
</li>
|
|
1718
|
-
{/* ... more features */}
|
|
1719
|
-
</ul>
|
|
1720
|
-
|
|
1721
|
-
<button className="w-full bg-primary text-primary-foreground py-2 rounded-lg">
|
|
1722
|
-
Get Started
|
|
1723
|
-
</button>
|
|
1724
|
-
</div>
|
|
1725
|
-
\`\`\`
|
|
1726
|
-
|
|
1727
|
-
## Testimonial Card
|
|
1728
|
-
\`\`\`tsx
|
|
1729
|
-
<div className="
|
|
1730
|
-
bg-card text-card-foreground
|
|
1731
|
-
rounded-xl border shadow-md
|
|
1732
|
-
p-6
|
|
1733
|
-
">
|
|
1734
|
-
<div className="flex items-center gap-4 mb-4">
|
|
1735
|
-
<img src="/avatar.jpg" className="w-12 h-12 rounded-full" />
|
|
1736
|
-
<div>
|
|
1737
|
-
<h4 className="font-semibold">John Doe</h4>
|
|
1738
|
-
<p className="text-sm text-muted-foreground">CEO, Company</p>
|
|
1739
|
-
</div>
|
|
1740
|
-
</div>
|
|
1741
|
-
<p className="text-muted-foreground italic">
|
|
1742
|
-
"This product is amazing! It has transformed how we work."
|
|
1743
|
-
</p>
|
|
1744
|
-
</div>
|
|
1745
|
-
\`\`\`
|
|
1746
|
-
`;
|
|
1747
|
-
|
|
1748
|
-
Write('design-system/patterns/cards.md', cardsPattern);
|
|
1749
|
-
|
|
1750
|
-
// ========== 5. forms.md ==========
|
|
1751
|
-
const formsPattern = `# Form Patterns
|
|
1752
|
-
|
|
1753
|
-
> **Source:** ${selectedStyle.site} | **Style:** ${selectedStyle.style}
|
|
1754
|
-
> **Load when:** Auth pages, settings, any form UI
|
|
1755
|
-
|
|
1756
|
-
## Input Field
|
|
1757
|
-
\`\`\`tsx
|
|
1758
|
-
<div className="space-y-2">
|
|
1759
|
-
<label className="text-sm font-medium text-foreground">
|
|
1760
|
-
Email Address
|
|
1761
|
-
</label>
|
|
1762
|
-
<input
|
|
1763
|
-
type="email"
|
|
1764
|
-
placeholder="you@example.com"
|
|
1765
|
-
className="
|
|
1766
|
-
w-full px-4 py-2
|
|
1767
|
-
bg-background text-foreground
|
|
1768
|
-
border rounded-md
|
|
1769
|
-
focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary
|
|
1770
|
-
placeholder:text-muted-foreground
|
|
1771
|
-
transition-all duration-200
|
|
1772
|
-
"
|
|
1773
|
-
/>
|
|
1774
|
-
<p className="text-sm text-muted-foreground">
|
|
1775
|
-
We'll never share your email.
|
|
1776
|
-
</p>
|
|
1777
|
-
</div>
|
|
1778
|
-
\`\`\`
|
|
1779
|
-
|
|
1780
|
-
## Input with Error
|
|
1781
|
-
\`\`\`tsx
|
|
1782
|
-
<div className="space-y-2">
|
|
1783
|
-
<label className="text-sm font-medium text-foreground">
|
|
1784
|
-
Password
|
|
1785
|
-
</label>
|
|
1786
|
-
<input
|
|
1787
|
-
type="password"
|
|
1788
|
-
className="
|
|
1789
|
-
w-full px-4 py-2
|
|
1790
|
-
bg-background text-foreground
|
|
1791
|
-
border border-error rounded-md
|
|
1792
|
-
focus:outline-none focus:ring-2 focus:ring-error/50
|
|
1793
|
-
"
|
|
1794
|
-
/>
|
|
1795
|
-
<p className="text-sm text-error">
|
|
1796
|
-
Password must be at least 8 characters.
|
|
1797
|
-
</p>
|
|
1798
|
-
</div>
|
|
1799
|
-
\`\`\`
|
|
1800
|
-
|
|
1801
|
-
## Select Field
|
|
1802
|
-
\`\`\`tsx
|
|
1803
|
-
<div className="space-y-2">
|
|
1804
|
-
<label className="text-sm font-medium text-foreground">
|
|
1805
|
-
Country
|
|
1806
|
-
</label>
|
|
1807
|
-
<select className="
|
|
1808
|
-
w-full px-4 py-2
|
|
1809
|
-
bg-background text-foreground
|
|
1810
|
-
border rounded-md
|
|
1811
|
-
focus:outline-none focus:ring-2 focus:ring-primary/50
|
|
1812
|
-
">
|
|
1813
|
-
<option value="">Select country</option>
|
|
1814
|
-
<option value="th">Thailand</option>
|
|
1815
|
-
<option value="us">United States</option>
|
|
1816
|
-
</select>
|
|
1817
|
-
</div>
|
|
1818
|
-
\`\`\`
|
|
1819
|
-
|
|
1820
|
-
## Checkbox
|
|
1821
|
-
\`\`\`tsx
|
|
1822
|
-
<label className="flex items-center gap-2 cursor-pointer">
|
|
1823
|
-
<input
|
|
1824
|
-
type="checkbox"
|
|
1825
|
-
className="
|
|
1826
|
-
w-4 h-4 rounded
|
|
1827
|
-
border border-border
|
|
1828
|
-
text-primary
|
|
1829
|
-
focus:ring-2 focus:ring-primary/50
|
|
1830
|
-
"
|
|
1831
|
-
/>
|
|
1832
|
-
<span className="text-sm text-foreground">
|
|
1833
|
-
I agree to the terms and conditions
|
|
1834
|
-
</span>
|
|
1835
|
-
</label>
|
|
1836
|
-
\`\`\`
|
|
1837
|
-
|
|
1838
|
-
## Form Layout
|
|
1839
|
-
\`\`\`tsx
|
|
1840
|
-
<form className="space-y-6 max-w-md mx-auto">
|
|
1841
|
-
{/* Form fields */}
|
|
1842
|
-
|
|
1843
|
-
<button
|
|
1844
|
-
type="submit"
|
|
1845
|
-
className="
|
|
1846
|
-
w-full bg-primary text-primary-foreground
|
|
1847
|
-
py-2 rounded-lg font-medium
|
|
1848
|
-
hover:bg-primary/90
|
|
1849
|
-
transition-all duration-200
|
|
1850
|
-
"
|
|
1851
|
-
>
|
|
1852
|
-
Submit
|
|
1853
|
-
</button>
|
|
1854
|
-
</form>
|
|
1855
|
-
\`\`\`
|
|
1856
|
-
`;
|
|
1857
|
-
|
|
1858
|
-
Write('design-system/patterns/forms.md', formsPattern);
|
|
1859
|
-
|
|
1860
|
-
output(`
|
|
1861
1121
|
✅ Pattern files generated:
|
|
1862
1122
|
- design-system/patterns/buttons.md
|
|
1863
1123
|
- design-system/patterns/scroll-animations.md
|
|
1864
1124
|
- design-system/patterns/decorations.md
|
|
1865
1125
|
- design-system/patterns/cards.md
|
|
1866
1126
|
- design-system/patterns/forms.md
|
|
1867
|
-
`);
|
|
1868
1127
|
```
|
|
1869
1128
|
|
|
1129
|
+
→ Continue to STEP 5.7
|
|
1130
|
+
|
|
1870
1131
|
---
|
|
1871
1132
|
|
|
1872
1133
|
## STEP 5.7: Generate Lean README.md (Human-Readable)
|
|
1873
1134
|
|
|
1874
1135
|
> **Human-readable guide** - No code, just descriptions and visuals
|
|
1875
1136
|
|
|
1876
|
-
|
|
1877
|
-
output(`
|
|
1878
|
-
🔄 Generating lean README.md (human-readable)...
|
|
1879
|
-
`);
|
|
1880
|
-
|
|
1881
|
-
const styleGuideMD = `# ${selectedStyle.style} Design System
|
|
1882
|
-
|
|
1883
|
-
> **Style:** ${selectedStyle.style}
|
|
1884
|
-
> **Theme:** ${selectedTheme.name}
|
|
1885
|
-
> **Generated:** ${new Date().toISOString().split('T')[0]}
|
|
1886
|
-
> **Sources:** ${Object.keys(extractedData).join(', ')}
|
|
1887
|
-
|
|
1888
|
-
---
|
|
1889
|
-
|
|
1890
|
-
## 1. Overview
|
|
1891
|
-
|
|
1892
|
-
This design system follows **${selectedStyle.style}** aesthetics with a **${selectedTheme.name}** theme.
|
|
1893
|
-
|
|
1894
|
-
### Feel
|
|
1895
|
-
${selectedStyle.feel}
|
|
1896
|
-
|
|
1897
|
-
### Characteristics
|
|
1898
|
-
${selectedStyle.characteristics.map(c => `- ${c}`).join('\n')}
|
|
1899
|
-
|
|
1900
|
-
---
|
|
1901
|
-
|
|
1902
|
-
## 2. Color Palette
|
|
1903
|
-
|
|
1904
|
-
### Primary Color
|
|
1905
|
-
- **Color:** ${tokensData.colors.primary.DEFAULT}
|
|
1906
|
-
- **Use for:** CTAs, links, accents, interactive elements
|
|
1907
|
-
- **Feel:** ${selectedStyle.feel}
|
|
1908
|
-
|
|
1909
|
-
### Secondary Color
|
|
1910
|
-
- **Color:** ${tokensData.colors.secondary.DEFAULT}
|
|
1911
|
-
- **Use for:** Secondary actions, less prominent elements
|
|
1912
|
-
|
|
1913
|
-
### Background Colors
|
|
1914
|
-
- **Main:** ${tokensData.colors.background.DEFAULT} (white)
|
|
1915
|
-
- **Muted:** ${tokensData.colors.background.muted} (subtle sections)
|
|
1916
|
-
- **Subtle:** ${tokensData.colors.background.subtle} (alternating sections)
|
|
1917
|
-
|
|
1918
|
-
### Text Colors
|
|
1919
|
-
- **Primary text:** ${tokensData.colors.foreground.DEFAULT}
|
|
1920
|
-
- **Muted text:** ${tokensData.colors.foreground.muted}
|
|
1921
|
-
- **Subtle text:** ${tokensData.colors.foreground.subtle}
|
|
1922
|
-
|
|
1923
|
-
### Semantic Colors
|
|
1924
|
-
- **Success:** ${tokensData.colors.semantic.success} (green)
|
|
1925
|
-
- **Warning:** ${tokensData.colors.semantic.warning} (amber)
|
|
1926
|
-
- **Error:** ${tokensData.colors.semantic.error} (red)
|
|
1927
|
-
- **Info:** ${tokensData.colors.semantic.info} (blue)
|
|
1928
|
-
|
|
1929
|
-
---
|
|
1930
|
-
|
|
1931
|
-
## 3. Typography
|
|
1137
|
+
### STEP 5.7.1: Display Progress Message
|
|
1932
1138
|
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
### Heading Sizes
|
|
1938
|
-
- **H1:** 48px bold - Hero headlines
|
|
1939
|
-
- **H2:** 36px bold - Section titles
|
|
1940
|
-
- **H3:** 30px semibold - Subsection titles
|
|
1941
|
-
- **H4:** 24px semibold - Card titles
|
|
1942
|
-
- **H5:** 20px medium - Feature titles
|
|
1943
|
-
- **H6:** 18px medium - Small titles
|
|
1944
|
-
|
|
1945
|
-
### Body Text
|
|
1946
|
-
- **Large:** 18px - Feature descriptions
|
|
1947
|
-
- **Base:** 16px - Body text
|
|
1948
|
-
- **Small:** 14px - Captions, labels
|
|
1949
|
-
- **Extra small:** 12px - Badges, tags
|
|
1950
|
-
|
|
1951
|
-
---
|
|
1952
|
-
|
|
1953
|
-
## 4. Spacing System
|
|
1954
|
-
|
|
1955
|
-
### Base Unit
|
|
1956
|
-
${tokensData.spacing.grid_base} grid system
|
|
1957
|
-
|
|
1958
|
-
### Scale
|
|
1959
|
-
${tokensData.spacing.scale.map(s => `- ${s}px`).join('\n')}
|
|
1960
|
-
|
|
1961
|
-
### Common Patterns
|
|
1962
|
-
- **Component padding:** 16px or 24px
|
|
1963
|
-
- **Section gap:** 32px or 48px
|
|
1964
|
-
- **Layout margin:** 64px or 96px
|
|
1965
|
-
|
|
1966
|
-
---
|
|
1967
|
-
|
|
1968
|
-
## 5. Shadows & Elevation
|
|
1969
|
-
|
|
1970
|
-
### Elevation Levels
|
|
1971
|
-
- **Level 0:** No shadow (flat elements)
|
|
1972
|
-
- **Level 1:** Subtle shadow (buttons on hover)
|
|
1973
|
-
- **Level 2:** Medium shadow (cards)
|
|
1974
|
-
- **Level 3:** Large shadow (dropdowns)
|
|
1975
|
-
- **Level 4:** Extra large shadow (modals)
|
|
1976
|
-
|
|
1977
|
-
### Usage
|
|
1978
|
-
- **Cards:** Medium shadow
|
|
1979
|
-
- **Dropdowns:** Large shadow
|
|
1980
|
-
- **Modals:** Extra large shadow
|
|
1981
|
-
- **Button hover:** Subtle shadow
|
|
1982
|
-
|
|
1983
|
-
---
|
|
1984
|
-
|
|
1985
|
-
## 6. Border Radius
|
|
1986
|
-
|
|
1987
|
-
### Values
|
|
1988
|
-
${tokensData.borders.radius.map(r => `- ${r}`).join('\n')}
|
|
1989
|
-
|
|
1990
|
-
### Usage
|
|
1991
|
-
- **Inputs:** Medium radius (8px)
|
|
1992
|
-
- **Buttons:** Large radius (12px)
|
|
1993
|
-
- **Cards:** Extra large radius (16px)
|
|
1994
|
-
- **Avatars:** Full radius (circle)
|
|
1995
|
-
|
|
1996
|
-
---
|
|
1139
|
+
Display progress message:
|
|
1140
|
+
```
|
|
1141
|
+
🔄 Generating lean README.md (human-readable)...
|
|
1142
|
+
```
|
|
1997
1143
|
|
|
1998
|
-
|
|
1144
|
+
### STEP 5.7.2: Build README Content
|
|
1999
1145
|
|
|
2000
|
-
|
|
2001
|
-
${selectedTheme.description}
|
|
1146
|
+
Build a markdown document with these 11 sections:
|
|
2002
1147
|
|
|
2003
|
-
|
|
2004
|
-
|
|
1148
|
+
**Header:**
|
|
1149
|
+
- Title: "[selectedStyle.style] Design System"
|
|
1150
|
+
- Metadata: Style, Theme, Generated date, Sources
|
|
2005
1151
|
|
|
2006
|
-
|
|
2007
|
-
|
|
1152
|
+
**Section 1: Overview**
|
|
1153
|
+
- Description of design system (style + theme)
|
|
1154
|
+
- Feel: selectedStyle.feel
|
|
1155
|
+
- Characteristics: List from selectedStyle.characteristics
|
|
2008
1156
|
|
|
2009
|
-
|
|
2010
|
-
|
|
1157
|
+
**Section 2: Color Palette**
|
|
1158
|
+
- Primary Color (value, usage, feel)
|
|
1159
|
+
- Secondary Color (value, usage)
|
|
1160
|
+
- Background Colors (DEFAULT, muted, subtle)
|
|
1161
|
+
- Text Colors (DEFAULT, muted, subtle)
|
|
1162
|
+
- Semantic Colors (success, warning, error, info)
|
|
2011
1163
|
|
|
2012
|
-
|
|
2013
|
-
|
|
1164
|
+
**Section 3: Typography**
|
|
1165
|
+
- Font Family (sans, monospace)
|
|
1166
|
+
- Heading Sizes (H1-H6 with px sizes and weights)
|
|
1167
|
+
- Body Text (large, base, small, extra small)
|
|
2014
1168
|
|
|
2015
|
-
|
|
1169
|
+
**Section 4: Spacing System**
|
|
1170
|
+
- Base Unit: tokensData.spacing.grid_base
|
|
1171
|
+
- Scale: List from tokensData.spacing.scale
|
|
1172
|
+
- Common Patterns (component padding, section gap, layout margin)
|
|
2016
1173
|
|
|
2017
|
-
|
|
1174
|
+
**Section 5: Shadows & Elevation**
|
|
1175
|
+
- Elevation Levels (0-4)
|
|
1176
|
+
- Usage guide for each level
|
|
2018
1177
|
|
|
2019
|
-
|
|
2020
|
-
|
|
1178
|
+
**Section 6: Border Radius**
|
|
1179
|
+
- Values: List from tokensData.borders.radius
|
|
1180
|
+
- Usage guide (inputs, buttons, cards, avatars)
|
|
2021
1181
|
|
|
2022
|
-
|
|
2023
|
-
|
|
1182
|
+
**Section 7: Theme**
|
|
1183
|
+
- Theme name: selectedTheme.name
|
|
1184
|
+
- Description and feeling
|
|
1185
|
+
- Decorative Elements to USE (list)
|
|
1186
|
+
- Elements to AVOID (list or "none specified")
|
|
1187
|
+
- Suggested Icons
|
|
2024
1188
|
|
|
2025
|
-
|
|
2026
|
-
|
|
1189
|
+
**Section 8: Animations**
|
|
1190
|
+
- Enabled status (Yes/No)
|
|
1191
|
+
- Libraries list or "CSS/Tailwind only"
|
|
1192
|
+
- Selected Patterns list or "No scroll animations"
|
|
1193
|
+
- Component Animations (button hover, card hover, input focus)
|
|
1194
|
+
- Timing (fast, normal, slow)
|
|
2027
1195
|
|
|
2028
|
-
|
|
2029
|
-
-
|
|
2030
|
-
-
|
|
2031
|
-
- **Input focus:** ${tokensData.animations.component_animations.input_focus}
|
|
1196
|
+
**Section 9: Component Library**
|
|
1197
|
+
- Recommended: tokensData.component_library.name
|
|
1198
|
+
- Common Components list
|
|
2032
1199
|
|
|
2033
|
-
|
|
2034
|
-
-
|
|
2035
|
-
- **Normal:** 200ms (most transitions)
|
|
2036
|
-
- **Slow:** 300ms (modals, page transitions)
|
|
1200
|
+
**Section 10: Code Patterns**
|
|
1201
|
+
- Reference links to all 5 pattern files
|
|
2037
1202
|
|
|
2038
|
-
|
|
1203
|
+
**Section 11: Critical Rules**
|
|
1204
|
+
- Colors rules (NO hardcoded hex, USE tokens)
|
|
1205
|
+
- Spacing rules (NO arbitrary values, USE scale)
|
|
1206
|
+
- Consistency rules (NO mixing, USE consistent patterns)
|
|
2039
1207
|
|
|
2040
|
-
|
|
1208
|
+
**Footer:**
|
|
1209
|
+
- "Generated by /designsetup v2.0.0"
|
|
1210
|
+
- "Sources: [list of extracted sites]"
|
|
2041
1211
|
|
|
2042
|
-
###
|
|
2043
|
-
${tokensData.component_library.name}
|
|
1212
|
+
### STEP 5.7.3: Write README File
|
|
2044
1213
|
|
|
2045
|
-
|
|
2046
|
-
${tokensData.component_library.common_components.map(c => `- ${c}`).join('\n')}
|
|
1214
|
+
Write the markdown content to `design-system/README.md`
|
|
2047
1215
|
|
|
2048
|
-
|
|
1216
|
+
### STEP 5.7.4: Display Confirmation
|
|
2049
1217
|
|
|
2050
|
-
|
|
1218
|
+
Display confirmation message:
|
|
1219
|
+
```
|
|
1220
|
+
✅ README.md generated (lean, human-readable, ~100 lines)
|
|
1221
|
+
```
|
|
2051
1222
|
|
|
2052
|
-
|
|
2053
|
-
- \`design-system/patterns/buttons.md\`
|
|
2054
|
-
- \`design-system/patterns/cards.md\`
|
|
2055
|
-
- \`design-system/patterns/forms.md\`
|
|
2056
|
-
- \`design-system/patterns/scroll-animations.md\`
|
|
2057
|
-
- \`design-system/patterns/decorations.md\`
|
|
1223
|
+
→ Continue to STEP 6
|
|
2058
1224
|
|
|
2059
1225
|
---
|
|
2060
1226
|
|
|
2061
|
-
##
|
|
2062
|
-
|
|
2063
|
-
### Colors
|
|
2064
|
-
- ❌ NO hardcoded hex values
|
|
2065
|
-
- ✅ USE theme tokens (bg-primary, text-foreground)
|
|
2066
|
-
|
|
2067
|
-
### Spacing
|
|
2068
|
-
- ❌ NO arbitrary values (p-5, gap-7)
|
|
2069
|
-
- ✅ USE spacing scale (p-4, p-6, gap-8)
|
|
2070
|
-
|
|
2071
|
-
### Consistency
|
|
2072
|
-
- ❌ NO mixing patterns
|
|
2073
|
-
- ✅ USE consistent patterns from tokens
|
|
2074
|
-
|
|
2075
|
-
---
|
|
1227
|
+
## STEP 6: Final Report
|
|
2076
1228
|
|
|
2077
|
-
|
|
2078
|
-
*Sources: ${Object.keys(extractedData).join(', ')}*
|
|
2079
|
-
`;
|
|
1229
|
+
Display a comprehensive final report with these sections:
|
|
2080
1230
|
|
|
2081
|
-
|
|
2082
|
-
output(`✅ README.md generated (lean, human-readable, ~100 lines)`);
|
|
1231
|
+
**Header:**
|
|
2083
1232
|
```
|
|
2084
|
-
|
|
2085
|
-
---
|
|
2086
|
-
|
|
2087
|
-
## STEP 6: Final Report
|
|
2088
|
-
|
|
2089
|
-
```javascript
|
|
2090
|
-
output(`
|
|
2091
1233
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
2092
1234
|
✅ Design Setup Complete!
|
|
2093
1235
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1236
|
+
```
|
|
2094
1237
|
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
1238
|
+
**Summary Section:**
|
|
1239
|
+
- Style: [selectedStyle.style] (from [selectedStyle.site])
|
|
1240
|
+
- Theme: [selectedTheme.name]
|
|
1241
|
+
- Sources: [list of extracted sites]
|
|
1242
|
+
- Animations: [count] patterns enabled
|
|
1243
|
+
|
|
1244
|
+
**Style Characteristics:**
|
|
1245
|
+
- List first 4 characteristics from selectedStyle.characteristics
|
|
1246
|
+
|
|
1247
|
+
**Theme Direction:**
|
|
1248
|
+
- USE: First 3 elements from selectedTheme.decorative_elements
|
|
1249
|
+
- AVOID: First 2 elements from selectedTheme.avoid_elements or "(none)"
|
|
1250
|
+
|
|
1251
|
+
**Files Created:**
|
|
1252
|
+
- FOR AGENTS section:
|
|
1253
|
+
- design-system/data.yaml (~300 lines)
|
|
1254
|
+
- design-system/patterns/buttons.md
|
|
1255
|
+
- design-system/patterns/cards.md
|
|
1256
|
+
- design-system/patterns/forms.md
|
|
1257
|
+
- design-system/patterns/scroll-animations.md
|
|
1258
|
+
- design-system/patterns/decorations.md
|
|
1259
|
+
|
|
1260
|
+
- FOR HUMANS section:
|
|
1261
|
+
- design-system/README.md (~100 lines)
|
|
1262
|
+
|
|
1263
|
+
**Next Steps:**
|
|
1264
|
+
1. Review generated files (commands provided)
|
|
1265
|
+
2. Plan your pages with /pageplan
|
|
1266
|
+
3. Setup & develop with /csetup and /cdev
|
|
1267
|
+
|
|
1268
|
+
**How It Works:**
|
|
1269
|
+
- Explain /pageplan reads data.yaml and auto-detects page type
|
|
1270
|
+
- Explain uxui-frontend agent reads data.yaml and selective patterns
|
|
1271
|
+
- Mention content includes Psychology, Target Audience, Why It Works
|
|
1272
|
+
|
|
1273
|
+
**Footer:**
|
|
1274
|
+
```
|
|
2123
1275
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1276
|
+
```
|
|
2124
1277
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
1. Review generated files:
|
|
2128
|
-
cat design-system/data.yaml | head -50
|
|
2129
|
-
cat design-system/README.md
|
|
2130
|
-
|
|
2131
|
-
2. Plan your pages:
|
|
2132
|
-
/pageplan @prd.md @project.md
|
|
2133
|
-
|
|
2134
|
-
3. Setup & develop:
|
|
2135
|
-
/csetup feature-landing
|
|
2136
|
-
/cdev feature-landing
|
|
2137
|
-
|
|
2138
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1278
|
+
---
|
|
2139
1279
|
|
|
2140
|
-
|
|
1280
|
+
## Helper: Generate data.yaml
|
|
2141
1281
|
|
|
2142
|
-
|
|
2143
|
-
→ data.yaml (style, theme, colors, animations, psychology)
|
|
2144
|
-
→ Auto-detects page type (landing/dashboard/auth)
|
|
2145
|
-
→ Loads patterns/*.md selectively
|
|
1282
|
+
This helper function generates the complete data.yaml file by merging psychology data from extracted sites with design tokens.
|
|
2146
1283
|
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
→ patterns/scroll-animations.md (landing pages only)
|
|
2152
|
-
→ patterns/decorations.md (landing pages only)
|
|
2153
|
-
→ patterns/forms.md (forms only)
|
|
1284
|
+
**Inputs:**
|
|
1285
|
+
- tokensData: Design tokens object built in STEP 5.5
|
|
1286
|
+
- extractedData: All extracted site data
|
|
1287
|
+
- selectedStyle: Selected style object from user choice
|
|
2154
1288
|
|
|
2155
|
-
|
|
1289
|
+
**Process:**
|
|
2156
1290
|
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
1291
|
+
1. Get psychology data from the selected site:
|
|
1292
|
+
- selectedSiteData = extractedData[selectedStyle.site]
|
|
1293
|
+
- psychology = selectedSiteData.psychology or empty object
|
|
1294
|
+
|
|
1295
|
+
2. Build YAML content with 5 major sections:
|
|
1296
|
+
|
|
1297
|
+
**Section 1: Header Comments**
|
|
1298
|
+
- Generated by: /designsetup
|
|
1299
|
+
- Source: selectedStyle.site
|
|
1300
|
+
- Style: selectedStyle.style
|
|
1301
|
+
|
|
1302
|
+
**Section 2: Meta**
|
|
1303
|
+
- generated_at: Current ISO timestamp
|
|
1304
|
+
- source_site: selectedStyle.site
|
|
1305
|
+
- style: selectedStyle.style
|
|
1306
|
+
- theme: tokensData.theme.name or "default"
|
|
1307
|
+
|
|
1308
|
+
**Section 3: Psychology & Analysis**
|
|
1309
|
+
- style_classification: From psychology or selectedStyle.style
|
|
1310
|
+
- emotions_evoked: List of {emotion, reason} or "# Not available"
|
|
1311
|
+
- target_audience:
|
|
1312
|
+
- primary: {description, age_range, tech_savvy}
|
|
1313
|
+
- secondary: {description}
|
|
1314
|
+
- visual_principles: List of {name, description} or "# Not available"
|
|
1315
|
+
- why_it_works: List of strings or "# Not available"
|
|
1316
|
+
- design_philosophy: {core_belief, key_principles list} or "Not specified"
|
|
1317
|
+
|
|
1318
|
+
**Section 4: Design Tokens**
|
|
1319
|
+
- style: {detected, characteristics list, feel}
|
|
1320
|
+
- colors: {primary, secondary, background, foreground, muted, accent}
|
|
1321
|
+
- typography: {font_family, heading_font, weights array, sizes object}
|
|
1322
|
+
- spacing: {base, scale array}
|
|
1323
|
+
- border_radius: {sm, md, lg, full}
|
|
1324
|
+
- shadows: {sm, md, lg}
|
|
1325
|
+
|
|
1326
|
+
**Section 5: Animations**
|
|
1327
|
+
- durations: {fast, normal, slow}
|
|
1328
|
+
- easing: {default, bounce}
|
|
1329
|
+
- component_animations: {button_hover, card_hover}
|
|
1330
|
+
- scroll_animations: {enabled boolean, patterns array}
|
|
1331
|
+
|
|
1332
|
+
**Section 6: Theme Direction**
|
|
1333
|
+
- theme: {name, decorative_elements list, avoid_elements list}
|
|
1334
|
+
|
|
1335
|
+
**Output:** Returns the complete YAML content as a string
|
|
2160
1336
|
|
|
2161
1337
|
---
|
|
2162
1338
|
|
|
2163
|
-
##
|
|
2164
|
-
|
|
2165
|
-
```javascript
|
|
2166
|
-
function generateDataYaml(tokensData, extractedData, selectedStyle) {
|
|
2167
|
-
// Get psychology from the selected extracted site
|
|
2168
|
-
const selectedSiteData = extractedData[selectedStyle.site];
|
|
2169
|
-
const psychology = selectedSiteData?.psychology || {};
|
|
2170
|
-
|
|
2171
|
-
return `# Design System Data
|
|
2172
|
-
# Generated by: /designsetup
|
|
2173
|
-
# Source: ${selectedStyle.site}
|
|
2174
|
-
# Style: ${selectedStyle.style}
|
|
1339
|
+
## Error Handling
|
|
2175
1340
|
|
|
2176
|
-
|
|
2177
|
-
generated_at: ${new Date().toISOString()}
|
|
2178
|
-
source_site: ${selectedStyle.site}
|
|
2179
|
-
style: ${selectedStyle.style}
|
|
2180
|
-
theme: ${tokensData.theme?.name || 'default'}
|
|
2181
|
-
|
|
2182
|
-
# ============================================
|
|
2183
|
-
# PSYCHOLOGY & ANALYSIS
|
|
2184
|
-
# ============================================
|
|
2185
|
-
|
|
2186
|
-
psychology:
|
|
2187
|
-
style_classification: ${psychology.style_classification || selectedStyle.style}
|
|
2188
|
-
|
|
2189
|
-
emotions_evoked:
|
|
2190
|
-
${(psychology.emotions_evoked || []).map(e => ` - emotion: "${e.emotion}"
|
|
2191
|
-
reason: "${e.reason}"`).join('\n') || ' # Not available'}
|
|
2192
|
-
|
|
2193
|
-
target_audience:
|
|
2194
|
-
primary:
|
|
2195
|
-
description: "${psychology.target_audience?.primary?.description || 'Not specified'}"
|
|
2196
|
-
age_range: "${psychology.target_audience?.primary?.age_range || 'mixed'}"
|
|
2197
|
-
tech_savvy: ${psychology.target_audience?.primary?.tech_savvy || 'medium'}
|
|
2198
|
-
secondary:
|
|
2199
|
-
description: "${psychology.target_audience?.secondary?.description || 'Not specified'}"
|
|
2200
|
-
|
|
2201
|
-
visual_principles:
|
|
2202
|
-
${(psychology.visual_principles || []).map(v => ` - name: "${v.name}"
|
|
2203
|
-
description: "${v.description}"`).join('\n') || ' # Not available'}
|
|
2204
|
-
|
|
2205
|
-
why_it_works:
|
|
2206
|
-
${(psychology.why_it_works || []).map(w => ` - "${w}"`).join('\n') || ' # Not available'}
|
|
2207
|
-
|
|
2208
|
-
design_philosophy:
|
|
2209
|
-
core_belief: "${psychology.design_philosophy?.core_belief || 'Not specified'}"
|
|
2210
|
-
key_principles:
|
|
2211
|
-
${(psychology.design_philosophy?.key_principles || []).map(p => ` - "${p}"`).join('\n') || ' # Not available'}
|
|
2212
|
-
|
|
2213
|
-
# ============================================
|
|
2214
|
-
# DESIGN TOKENS
|
|
2215
|
-
# ============================================
|
|
2216
|
-
|
|
2217
|
-
style:
|
|
2218
|
-
detected: ${tokensData.style.detected}
|
|
2219
|
-
characteristics:
|
|
2220
|
-
${tokensData.style.characteristics.map(c => ` - "${c}"`).join('\n')}
|
|
2221
|
-
feel: "${tokensData.style.feel}"
|
|
1341
|
+
Handle these error scenarios throughout the workflow:
|
|
2222
1342
|
|
|
2223
|
-
|
|
2224
|
-
primary: "${tokensData.colors.primary}"
|
|
2225
|
-
secondary: "${tokensData.colors.secondary}"
|
|
2226
|
-
background: "${tokensData.colors.background}"
|
|
2227
|
-
foreground: "${tokensData.colors.foreground}"
|
|
2228
|
-
muted: "${tokensData.colors.muted}"
|
|
2229
|
-
accent: "${tokensData.colors.accent}"
|
|
1343
|
+
### Error 1: No Extracted Data (STEP 0.1)
|
|
2230
1344
|
|
|
2231
|
-
|
|
2232
|
-
font_family: "${tokensData.typography.font_family}"
|
|
2233
|
-
heading_font: "${tokensData.typography.heading_font}"
|
|
2234
|
-
weights: [${tokensData.typography.weights.join(', ')}]
|
|
2235
|
-
sizes:
|
|
2236
|
-
h1: "${tokensData.typography.sizes.h1}"
|
|
2237
|
-
h2: "${tokensData.typography.sizes.h2}"
|
|
2238
|
-
h3: "${tokensData.typography.sizes.h3}"
|
|
2239
|
-
body: "${tokensData.typography.sizes.body}"
|
|
2240
|
-
small: "${tokensData.typography.sizes.small}"
|
|
1345
|
+
**When:** No design-system/extracted/*/data.yaml files found
|
|
2241
1346
|
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
1347
|
+
**Action:** Display error message and stop execution:
|
|
1348
|
+
```
|
|
1349
|
+
❌ No extracted data found
|
|
2245
1350
|
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
md: "${tokensData.border_radius.md}"
|
|
2249
|
-
lg: "${tokensData.border_radius.lg}"
|
|
2250
|
-
full: "${tokensData.border_radius.full}"
|
|
1351
|
+
Please extract at least 1 site:
|
|
1352
|
+
/extract https://airbnb.com
|
|
2251
1353
|
|
|
2252
|
-
|
|
2253
|
-
sm: "${tokensData.shadows.sm}"
|
|
2254
|
-
md: "${tokensData.shadows.md}"
|
|
2255
|
-
lg: "${tokensData.shadows.lg}"
|
|
2256
|
-
|
|
2257
|
-
# ============================================
|
|
2258
|
-
# ANIMATIONS
|
|
2259
|
-
# ============================================
|
|
2260
|
-
|
|
2261
|
-
animations:
|
|
2262
|
-
durations:
|
|
2263
|
-
fast: "${tokensData.animations.durations.fast}"
|
|
2264
|
-
normal: "${tokensData.animations.durations.normal}"
|
|
2265
|
-
slow: "${tokensData.animations.durations.slow}"
|
|
2266
|
-
easing:
|
|
2267
|
-
default: "${tokensData.animations.easing.default}"
|
|
2268
|
-
bounce: "${tokensData.animations.easing.bounce}"
|
|
2269
|
-
component_animations:
|
|
2270
|
-
button_hover: "${tokensData.animations.component_animations.button_hover}"
|
|
2271
|
-
card_hover: "${tokensData.animations.component_animations.card_hover}"
|
|
2272
|
-
scroll_animations:
|
|
2273
|
-
enabled: ${tokensData.animations.scroll_animations.enabled}
|
|
2274
|
-
patterns:
|
|
2275
|
-
${(tokensData.animations.scroll_animations.patterns || []).map(p => ` - "${p}"`).join('\n')}
|
|
2276
|
-
|
|
2277
|
-
# ============================================
|
|
2278
|
-
# THEME DIRECTION
|
|
2279
|
-
# ============================================
|
|
2280
|
-
|
|
2281
|
-
theme:
|
|
2282
|
-
name: "${tokensData.theme?.name || 'default'}"
|
|
2283
|
-
decorative_elements:
|
|
2284
|
-
${(tokensData.theme?.decorative_elements || []).map(d => ` - "${d}"`).join('\n')}
|
|
2285
|
-
avoid_elements:
|
|
2286
|
-
${(tokensData.theme?.avoid_elements || []).map(a => ` - "${a}"`).join('\n')}
|
|
2287
|
-
`;
|
|
2288
|
-
}
|
|
1354
|
+
Then run: /designsetup @prd.md
|
|
2289
1355
|
```
|
|
2290
1356
|
|
|
2291
|
-
|
|
1357
|
+
### Error 2: AI Analysis Fails (STEP 1.2, 2.3, etc.)
|
|
2292
1358
|
|
|
2293
|
-
|
|
1359
|
+
**When:** LLM call fails during context analysis or style generation
|
|
2294
1360
|
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
return error(`
|
|
2299
|
-
❌ No extracted data found
|
|
1361
|
+
**Action:** Catch error and display message with debugging guidance:
|
|
1362
|
+
```
|
|
1363
|
+
❌ AI analysis failed: [error.message]
|
|
2300
1364
|
|
|
2301
|
-
|
|
2302
|
-
|
|
1365
|
+
This may be due to:
|
|
1366
|
+
- Extracted data too large (try fewer sites)
|
|
1367
|
+
- API rate limit (wait and retry)
|
|
1368
|
+
- Invalid context files
|
|
2303
1369
|
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
}
|
|
1370
|
+
Retry or use --debug for details
|
|
1371
|
+
```
|
|
2307
1372
|
|
|
2308
|
-
|
|
2309
|
-
try {
|
|
2310
|
-
const styleOptions = await LLM({ ... });
|
|
2311
|
-
} catch (error) {
|
|
2312
|
-
return error(`
|
|
2313
|
-
❌ AI analysis failed: ${error.message}
|
|
1373
|
+
### Error 3: User Cancels (STEP 2.8)
|
|
2314
1374
|
|
|
2315
|
-
|
|
2316
|
-
- Extracted data too large (try fewer sites)
|
|
2317
|
-
- API rate limit (wait and retry)
|
|
2318
|
-
- Invalid context files
|
|
1375
|
+
**When:** User selects "Cancel" option at max rounds or during confirmation
|
|
2319
1376
|
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
1377
|
+
**Action:** Display cancellation message and preserve data:
|
|
1378
|
+
```
|
|
1379
|
+
⚠️ Design setup cancelled
|
|
2323
1380
|
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
⚠️ Design setup cancelled
|
|
1381
|
+
Your data is preserved:
|
|
1382
|
+
- Extracted: design-system/extracted/
|
|
1383
|
+
- Options: design-system/synthesis/options/
|
|
2328
1384
|
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
- Options: design-system/synthesis/options/
|
|
1385
|
+
Run /designsetup again when ready.
|
|
1386
|
+
```
|
|
2332
1387
|
|
|
2333
|
-
|
|
2334
|
-
`);
|
|
2335
|
-
return;
|
|
2336
|
-
}
|
|
1388
|
+
### Error 4: Write Fails (STEP 5.6, 5.7)
|
|
2337
1389
|
|
|
2338
|
-
|
|
2339
|
-
try {
|
|
2340
|
-
Write('design-system/README.md', styleGuideMD);
|
|
2341
|
-
} catch (error) {
|
|
2342
|
-
// Save backup
|
|
2343
|
-
Write('/tmp/style-guide-backup.md', styleGuideMD);
|
|
1390
|
+
**When:** Unable to write to design-system/ directory
|
|
2344
1391
|
|
|
2345
|
-
|
|
2346
|
-
|
|
1392
|
+
**Action:**
|
|
1393
|
+
1. Save backup to temporary location: /tmp/style-guide-backup.md
|
|
1394
|
+
2. Display error message with backup location:
|
|
1395
|
+
```
|
|
1396
|
+
❌ Failed to write README.md
|
|
2347
1397
|
|
|
2348
|
-
|
|
1398
|
+
Check permissions: design-system/
|
|
2349
1399
|
|
|
2350
|
-
|
|
2351
|
-
`);
|
|
2352
|
-
}
|
|
1400
|
+
Backup saved: /tmp/style-guide-backup.md
|
|
2353
1401
|
```
|
|
2354
1402
|
|
|
2355
1403
|
---
|