@fr0mpy/component-system 2.0.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/bin/cli.js +283 -0
- package/index.js +12 -0
- package/package.json +45 -0
- package/templates/commands/component-harness.md +116 -0
- package/templates/commands/setup-styling.md +111 -0
- package/templates/component-recipes/accordion.md +153 -0
- package/templates/component-recipes/alert.md +145 -0
- package/templates/component-recipes/avatar.md +165 -0
- package/templates/component-recipes/badge.md +126 -0
- package/templates/component-recipes/breadcrumb.md +220 -0
- package/templates/component-recipes/button.md +90 -0
- package/templates/component-recipes/card.md +130 -0
- package/templates/component-recipes/carousel.md +277 -0
- package/templates/component-recipes/checkbox.md +117 -0
- package/templates/component-recipes/collapsible.md +201 -0
- package/templates/component-recipes/combobox.md +193 -0
- package/templates/component-recipes/context-menu.md +254 -0
- package/templates/component-recipes/dialog.md +193 -0
- package/templates/component-recipes/drawer.md +196 -0
- package/templates/component-recipes/dropdown-menu.md +263 -0
- package/templates/component-recipes/hover-card.md +230 -0
- package/templates/component-recipes/input.md +113 -0
- package/templates/component-recipes/label.md +259 -0
- package/templates/component-recipes/modal.md +155 -0
- package/templates/component-recipes/navigation-menu.md +310 -0
- package/templates/component-recipes/pagination.md +223 -0
- package/templates/component-recipes/popover.md +156 -0
- package/templates/component-recipes/progress.md +185 -0
- package/templates/component-recipes/radio.md +148 -0
- package/templates/component-recipes/select.md +154 -0
- package/templates/component-recipes/separator.md +124 -0
- package/templates/component-recipes/skeleton.md +186 -0
- package/templates/component-recipes/slider.md +114 -0
- package/templates/component-recipes/spinner.md +225 -0
- package/templates/component-recipes/switch.md +100 -0
- package/templates/component-recipes/table.md +161 -0
- package/templates/component-recipes/tabs.md +145 -0
- package/templates/component-recipes/textarea.md +234 -0
- package/templates/component-recipes/toast.md +209 -0
- package/templates/component-recipes/toggle-group.md +216 -0
- package/templates/component-recipes/tooltip.md +115 -0
- package/templates/hooks/triggers.d/styling.json +23 -0
- package/templates/skills/styling.md +173 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
7
|
+
const TARGET_DIR = path.join(process.cwd(), '.claude');
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
// Parse flags
|
|
11
|
+
const hasFlag = (...flags) => flags.some((f) => args.includes(f));
|
|
12
|
+
const forceMode = hasFlag('--force', '-f');
|
|
13
|
+
const mergeMode = hasFlag('--merge', '-m');
|
|
14
|
+
const removeMode = hasFlag('--remove', '--uninstall', '-r');
|
|
15
|
+
const helpMode = hasFlag('--help', '-h');
|
|
16
|
+
const updateSkills = hasFlag('--update-skills');
|
|
17
|
+
const updateRecipes = hasFlag('--update-recipes');
|
|
18
|
+
const updateCommands = hasFlag('--update-commands');
|
|
19
|
+
const updateMode = updateSkills || updateRecipes || updateCommands;
|
|
20
|
+
|
|
21
|
+
function copyDir(src, dest) {
|
|
22
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
23
|
+
|
|
24
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
25
|
+
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const srcPath = path.join(src, entry.name);
|
|
28
|
+
const destPath = path.join(dest, entry.name);
|
|
29
|
+
|
|
30
|
+
if (entry.isDirectory()) {
|
|
31
|
+
copyDir(srcPath, destPath);
|
|
32
|
+
} else {
|
|
33
|
+
fs.copyFileSync(srcPath, destPath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function copySubdir(subdir) {
|
|
39
|
+
const src = path.join(TEMPLATES_DIR, subdir);
|
|
40
|
+
const dest = path.join(TARGET_DIR, subdir);
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(src)) {
|
|
43
|
+
console.error(`❌ Source directory not found: ${subdir}`);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (fs.existsSync(dest)) {
|
|
48
|
+
fs.rmSync(dest, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
copyDir(src, dest);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function injectStylingTrigger() {
|
|
56
|
+
const triggersDDir = path.join(TARGET_DIR, 'hooks', 'triggers.d');
|
|
57
|
+
const stylingTriggerSrc = path.join(TEMPLATES_DIR, 'hooks', 'triggers.d', 'styling.json');
|
|
58
|
+
const stylingTriggerDest = path.join(triggersDDir, 'styling.json');
|
|
59
|
+
|
|
60
|
+
if (fs.existsSync(triggersDDir) && fs.existsSync(stylingTriggerSrc)) {
|
|
61
|
+
fs.copyFileSync(stylingTriggerSrc, stylingTriggerDest);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function removeStylingTrigger() {
|
|
68
|
+
const stylingTrigger = path.join(TARGET_DIR, 'hooks', 'triggers.d', 'styling.json');
|
|
69
|
+
if (fs.existsSync(stylingTrigger)) {
|
|
70
|
+
fs.unlinkSync(stylingTrigger);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function init() {
|
|
77
|
+
console.log('🎨 Initializing Claude Code component system...\n');
|
|
78
|
+
|
|
79
|
+
const promptSystemExists = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
|
|
80
|
+
const componentSystemExists = fs.existsSync(path.join(TARGET_DIR, 'skills')) ||
|
|
81
|
+
fs.existsSync(path.join(TARGET_DIR, 'component-recipes'));
|
|
82
|
+
|
|
83
|
+
if (componentSystemExists && !forceMode && !mergeMode) {
|
|
84
|
+
console.log('⚠️ Component system already exists in .claude/');
|
|
85
|
+
console.log(' Use --force to overwrite, --merge to update, or use selective updates:');
|
|
86
|
+
console.log(' --update-skills, --update-recipes, --update-commands\n');
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!fs.existsSync(TEMPLATES_DIR)) {
|
|
91
|
+
console.error('❌ Templates directory not found. Package may be corrupted.');
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Create .claude if it doesn't exist
|
|
96
|
+
fs.mkdirSync(TARGET_DIR, { recursive: true });
|
|
97
|
+
|
|
98
|
+
if (forceMode && componentSystemExists) {
|
|
99
|
+
// Only remove component-system specific dirs
|
|
100
|
+
const componentDirs = ['skills', 'component-recipes'];
|
|
101
|
+
for (const dir of componentDirs) {
|
|
102
|
+
const dirPath = path.join(TARGET_DIR, dir);
|
|
103
|
+
if (fs.existsSync(dirPath)) {
|
|
104
|
+
fs.rmSync(dirPath, { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
console.log('🗑️ Removed existing component system files.\n');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Copy component system templates
|
|
111
|
+
copyDir(path.join(TEMPLATES_DIR, 'skills'), path.join(TARGET_DIR, 'skills'));
|
|
112
|
+
copyDir(path.join(TEMPLATES_DIR, 'component-recipes'), path.join(TARGET_DIR, 'component-recipes'));
|
|
113
|
+
|
|
114
|
+
// Copy styling commands
|
|
115
|
+
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
116
|
+
fs.mkdirSync(commandsDir, { recursive: true });
|
|
117
|
+
fs.copyFileSync(
|
|
118
|
+
path.join(TEMPLATES_DIR, 'commands', 'setup-styling.md'),
|
|
119
|
+
path.join(commandsDir, 'setup-styling.md')
|
|
120
|
+
);
|
|
121
|
+
fs.copyFileSync(
|
|
122
|
+
path.join(TEMPLATES_DIR, 'commands', 'component-harness.md'),
|
|
123
|
+
path.join(commandsDir, 'component-harness.md')
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
console.log('✅ Created component system files:');
|
|
127
|
+
console.log(' 📁 skills/ - Styling skill for UI generation');
|
|
128
|
+
console.log(' 📁 component-recipes/ - 36 component templates');
|
|
129
|
+
console.log(' 📄 commands/setup-styling.md');
|
|
130
|
+
console.log(' 📄 commands/component-harness.md\n');
|
|
131
|
+
|
|
132
|
+
// Inject styling trigger if prompt-system is installed
|
|
133
|
+
if (promptSystemExists) {
|
|
134
|
+
if (injectStylingTrigger()) {
|
|
135
|
+
console.log('✅ Injected styling trigger into prompt system.');
|
|
136
|
+
console.log(' Styling-related prompts will now auto-trigger the styling skill.\n');
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
console.log('ℹ️ Prompt system not detected.');
|
|
140
|
+
console.log(' For auto-triggering styling rules, also install:');
|
|
141
|
+
console.log(' npx @fr0mpy/prompt-system\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log('🚀 Ready! Use /setup-styling to configure your design system.\n');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function update() {
|
|
148
|
+
if (!fs.existsSync(TARGET_DIR)) {
|
|
149
|
+
console.error('❌ .claude directory not found. Run without flags to initialize first.');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log('🔄 Updating selected components...\n');
|
|
154
|
+
|
|
155
|
+
const updates = [];
|
|
156
|
+
|
|
157
|
+
if (updateSkills && copySubdir('skills')) updates.push('skills');
|
|
158
|
+
if (updateRecipes && copySubdir('component-recipes')) updates.push('component-recipes');
|
|
159
|
+
if (updateCommands) {
|
|
160
|
+
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
161
|
+
fs.mkdirSync(commandsDir, { recursive: true });
|
|
162
|
+
fs.copyFileSync(
|
|
163
|
+
path.join(TEMPLATES_DIR, 'commands', 'setup-styling.md'),
|
|
164
|
+
path.join(commandsDir, 'setup-styling.md')
|
|
165
|
+
);
|
|
166
|
+
fs.copyFileSync(
|
|
167
|
+
path.join(TEMPLATES_DIR, 'commands', 'component-harness.md'),
|
|
168
|
+
path.join(commandsDir, 'component-harness.md')
|
|
169
|
+
);
|
|
170
|
+
updates.push('commands');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (updates.length > 0) {
|
|
174
|
+
console.log(`✅ Updated: ${updates.join(', ')}\n`);
|
|
175
|
+
} else {
|
|
176
|
+
console.log('⚠️ No components updated.\n');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function remove() {
|
|
181
|
+
if (!fs.existsSync(TARGET_DIR)) {
|
|
182
|
+
console.log('ℹ️ .claude directory does not exist. Nothing to remove.\n');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check if prompt-system exists - if so, only remove component-system files
|
|
187
|
+
const hasHooks = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
|
|
188
|
+
|
|
189
|
+
const componentDirs = ['skills', 'component-recipes'];
|
|
190
|
+
const componentCommands = ['setup-styling.md', 'component-harness.md'];
|
|
191
|
+
|
|
192
|
+
for (const dir of componentDirs) {
|
|
193
|
+
const dirPath = path.join(TARGET_DIR, dir);
|
|
194
|
+
if (fs.existsSync(dirPath)) {
|
|
195
|
+
fs.rmSync(dirPath, { recursive: true });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Remove styling commands
|
|
200
|
+
const commandsDir = path.join(TARGET_DIR, 'commands');
|
|
201
|
+
if (fs.existsSync(commandsDir)) {
|
|
202
|
+
for (const cmd of componentCommands) {
|
|
203
|
+
const cmdPath = path.join(commandsDir, cmd);
|
|
204
|
+
if (fs.existsSync(cmdPath)) {
|
|
205
|
+
fs.unlinkSync(cmdPath);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Remove styling trigger
|
|
211
|
+
removeStylingTrigger();
|
|
212
|
+
|
|
213
|
+
// Remove styling-config.json if it exists
|
|
214
|
+
const stylingConfig = path.join(TARGET_DIR, 'styling-config.json');
|
|
215
|
+
if (fs.existsSync(stylingConfig)) {
|
|
216
|
+
fs.unlinkSync(stylingConfig);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (hasHooks) {
|
|
220
|
+
console.log('✅ Removed component system files. Prompt system preserved.\n');
|
|
221
|
+
} else {
|
|
222
|
+
// If nothing else remains, remove .claude entirely
|
|
223
|
+
const remaining = fs.readdirSync(TARGET_DIR);
|
|
224
|
+
if (remaining.length === 0 || (remaining.length === 1 && remaining[0] === 'commands')) {
|
|
225
|
+
fs.rmSync(TARGET_DIR, { recursive: true });
|
|
226
|
+
console.log('✅ Removed .claude directory.\n');
|
|
227
|
+
} else {
|
|
228
|
+
console.log('✅ Removed component system files.\n');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function showHelp() {
|
|
234
|
+
console.log(`
|
|
235
|
+
@fr0mpy/component-system - Claude Code UI styling and component system
|
|
236
|
+
|
|
237
|
+
Usage:
|
|
238
|
+
npx @fr0mpy/component-system Initialize in current directory
|
|
239
|
+
npx @fr0mpy/component-system --merge Add to existing .claude (default behavior)
|
|
240
|
+
npx @fr0mpy/component-system --force Overwrite existing component files
|
|
241
|
+
npx @fr0mpy/component-system --remove Remove component system files
|
|
242
|
+
|
|
243
|
+
Selective updates:
|
|
244
|
+
--update-skills Update only skills/
|
|
245
|
+
--update-recipes Update only component-recipes/
|
|
246
|
+
--update-commands Update only styling commands
|
|
247
|
+
|
|
248
|
+
Options:
|
|
249
|
+
-h, --help Show this help message
|
|
250
|
+
-f, --force Overwrite existing component system files
|
|
251
|
+
-m, --merge Merge with existing .claude directory
|
|
252
|
+
-r, --remove Remove component system (alias: --uninstall)
|
|
253
|
+
|
|
254
|
+
What's included:
|
|
255
|
+
• skills/ Styling skill for consistent UI generation
|
|
256
|
+
• component-recipes/ 36 pre-built component templates
|
|
257
|
+
• commands/ /setup-styling, /component-harness
|
|
258
|
+
|
|
259
|
+
Getting started:
|
|
260
|
+
1. Run: npx @fr0mpy/component-system
|
|
261
|
+
2. Use: /setup-styling to configure your design system
|
|
262
|
+
3. Use: /component-harness to preview components
|
|
263
|
+
|
|
264
|
+
For prompt injection and agents:
|
|
265
|
+
npx @fr0mpy/prompt-system
|
|
266
|
+
|
|
267
|
+
Learn more: https://github.com/fr0mpy/claude-base-setup
|
|
268
|
+
`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function main() {
|
|
272
|
+
if (helpMode) {
|
|
273
|
+
showHelp();
|
|
274
|
+
} else if (removeMode) {
|
|
275
|
+
remove();
|
|
276
|
+
} else if (updateMode) {
|
|
277
|
+
await update();
|
|
278
|
+
} else {
|
|
279
|
+
await init();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
main();
|
package/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @claude-tools/component-system
|
|
3
|
+
*
|
|
4
|
+
* Claude Code UI styling system with design tokens, component recipes, and visual preview harness.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
name: '@claude-tools/component-system',
|
|
11
|
+
templatesDir: path.join(__dirname, 'templates'),
|
|
12
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fr0mpy/component-system",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Claude Code UI styling system with design tokens, 36 component recipes, and visual harness",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"fromp-component-system": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Tests not yet configured\""
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"claude",
|
|
14
|
+
"claude-code",
|
|
15
|
+
"ui",
|
|
16
|
+
"components",
|
|
17
|
+
"tailwind",
|
|
18
|
+
"design-tokens",
|
|
19
|
+
"styling",
|
|
20
|
+
"react"
|
|
21
|
+
],
|
|
22
|
+
"author": "fr0mpy",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/fr0mpy/claude-base-setup.git",
|
|
27
|
+
"directory": "packages/component-system"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/",
|
|
31
|
+
"templates/",
|
|
32
|
+
"index.js"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=16.0.0"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@fr0mpy/prompt-system": ">=2.0.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"@fr0mpy/prompt-system": {
|
|
42
|
+
"optional": true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Launch the visual component harness to preview and iterate on your design system components.
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
- Run `/setup-styling` first to generate styling config and component recipes
|
|
5
|
+
- Node.js 18+ installed
|
|
6
|
+
|
|
7
|
+
## Workflow
|
|
8
|
+
|
|
9
|
+
1. **Check for styling config**
|
|
10
|
+
- If `.claude/styling-config.json` doesn't exist, prompt to run `/setup-styling` first
|
|
11
|
+
|
|
12
|
+
2. **Check if component-harness exists**
|
|
13
|
+
- Look for `component-harness/` directory in project root
|
|
14
|
+
- If not found, scaffold it from templates
|
|
15
|
+
|
|
16
|
+
3. **Scaffold component-harness** (if needed)
|
|
17
|
+
Create the following structure:
|
|
18
|
+
```
|
|
19
|
+
component-harness/
|
|
20
|
+
├── index.html
|
|
21
|
+
├── main.tsx
|
|
22
|
+
├── App.tsx
|
|
23
|
+
├── Gallery.tsx
|
|
24
|
+
├── ComponentPreview.tsx
|
|
25
|
+
├── components/ # Generated components go here
|
|
26
|
+
│ ├── Button.tsx
|
|
27
|
+
│ ├── Card.tsx
|
|
28
|
+
│ └── ...
|
|
29
|
+
├── lib/
|
|
30
|
+
│ └── utils.ts # cn() utility
|
|
31
|
+
├── vite.config.ts
|
|
32
|
+
├── tailwind.config.ts
|
|
33
|
+
├── postcss.config.js
|
|
34
|
+
├── tsconfig.json
|
|
35
|
+
└── package.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
4. **Generate components from recipes (resumable)**
|
|
39
|
+
- List all `.claude/component-recipes/*.md` files
|
|
40
|
+
- For each recipe, check if matching `.tsx` component exists
|
|
41
|
+
- Only generate missing components (skip existing ones)
|
|
42
|
+
- Use tokens from `.claude/styling-config.json`
|
|
43
|
+
- Update `components/index.ts` to export all components
|
|
44
|
+
|
|
45
|
+
5. **Validate completeness**
|
|
46
|
+
- Count recipes vs generated components
|
|
47
|
+
- If any missing, loop back to step 4
|
|
48
|
+
- Only proceed when: `✓ [N]/[N] components generated`
|
|
49
|
+
|
|
50
|
+
6. **Install dependencies** (if package.json is new)
|
|
51
|
+
```bash
|
|
52
|
+
cd component-harness && npm install
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
7. **Start dev server**
|
|
56
|
+
```bash
|
|
57
|
+
cd component-harness && npm run dev
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
8. **Open browser**
|
|
61
|
+
- Open `http://localhost:5173` (or configured port)
|
|
62
|
+
|
|
63
|
+
## Harness Features
|
|
64
|
+
|
|
65
|
+
### Navigation
|
|
66
|
+
- Left/right chevron buttons to cycle through components
|
|
67
|
+
- Component name displayed in header
|
|
68
|
+
- Variant selector for components with multiple variants
|
|
69
|
+
|
|
70
|
+
### Live Preview
|
|
71
|
+
- Component rendered in isolated preview area
|
|
72
|
+
- Props can be adjusted in real-time
|
|
73
|
+
- Dark/light mode toggle
|
|
74
|
+
|
|
75
|
+
### Change Requests
|
|
76
|
+
- "Request Change" button that:
|
|
77
|
+
1. Prompts user to describe desired change
|
|
78
|
+
2. Claude updates the recipe and regenerates component
|
|
79
|
+
3. HMR updates the preview instantly
|
|
80
|
+
|
|
81
|
+
## Generated Gallery.tsx Structure
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// Core navigation and preview
|
|
85
|
+
- useState for currentComponentIndex
|
|
86
|
+
- Array of all components with their variants
|
|
87
|
+
- Left/Right chevron navigation
|
|
88
|
+
- Component name + variant display
|
|
89
|
+
- Isolated preview area
|
|
90
|
+
- "Request Change" button
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## package.json Dependencies
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"dependencies": {
|
|
98
|
+
"react": "^18.2.0",
|
|
99
|
+
"react-dom": "^18.2.0",
|
|
100
|
+
"clsx": "^2.0.0",
|
|
101
|
+
"tailwind-merge": "^2.0.0",
|
|
102
|
+
"lucide-react": "^0.300.0",
|
|
103
|
+
"@radix-ui/react-slot": "^1.0.0"
|
|
104
|
+
},
|
|
105
|
+
"devDependencies": {
|
|
106
|
+
"vite": "^5.0.0",
|
|
107
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
108
|
+
"typescript": "^5.0.0",
|
|
109
|
+
"tailwindcss": "^3.4.0",
|
|
110
|
+
"postcss": "^8.0.0",
|
|
111
|
+
"autoprefixer": "^10.0.0"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Define your unique UI aesthetic for consistent component generation.
|
|
2
|
+
|
|
3
|
+
This command creates a personalized styling system. Once configured, the `styling` skill will automatically apply these tokens and recipes when generating UI components.
|
|
4
|
+
|
|
5
|
+
## Workflow
|
|
6
|
+
|
|
7
|
+
1. **Check for existing tokens** - Look for `tailwind.config.*` or existing `.claude/styling-config.json`
|
|
8
|
+
2. **Ask aesthetic questions** using AskUserQuestion tool:
|
|
9
|
+
|
|
10
|
+
**Q1: Import existing?**
|
|
11
|
+
- If `tailwind.config.*` found: "Found tailwind config. Import colors/spacing from it?"
|
|
12
|
+
- Options: [Yes, import] [No, start fresh]
|
|
13
|
+
|
|
14
|
+
**Q2: Overall aesthetic feel**
|
|
15
|
+
- Options: [Minimal - clean, lots of whitespace] [Bold - strong colors, high contrast] [Playful - rounded, colorful, fun] [Enterprise - professional, structured] [Custom - I'll describe it]
|
|
16
|
+
|
|
17
|
+
**Q3: Color philosophy**
|
|
18
|
+
- Options: [Monochrome - shades of one color] [Vibrant - bright, saturated colors] [Muted pastels - soft, calm colors] [Earth tones - natural, warm colors] [Custom - I'll provide hex values]
|
|
19
|
+
- If Custom: Ask for primary, secondary, background, surface, text colors
|
|
20
|
+
|
|
21
|
+
**Q4: Typography**
|
|
22
|
+
- Options: [Modern sans (Inter/system)] [Classic serif] [Monospace/technical] [Custom font family]
|
|
23
|
+
|
|
24
|
+
**Q5: Component personality**
|
|
25
|
+
- Corners: [Sharp (rounded-none)] [Subtle (rounded-sm)] [Rounded (rounded-lg)] [Pill (rounded-full)]
|
|
26
|
+
- Shadows: [Flat (no shadows)] [Subtle (shadow-sm)] [Pronounced (shadow-lg)] [Glassmorphism]
|
|
27
|
+
- Density: [Compact (tight spacing)] [Comfortable (normal)] [Spacious (generous padding)]
|
|
28
|
+
|
|
29
|
+
3. **Generate `.claude/styling-config.json`** with structure:
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"aesthetic": "minimal",
|
|
33
|
+
"tokens": {
|
|
34
|
+
"colors": {
|
|
35
|
+
"primary": "#0066FF",
|
|
36
|
+
"primary-foreground": "#FFFFFF",
|
|
37
|
+
"secondary": "#6C5CE7",
|
|
38
|
+
"secondary-foreground": "#FFFFFF",
|
|
39
|
+
"background": "#FFFFFF",
|
|
40
|
+
"foreground": "#1A1A1A",
|
|
41
|
+
"surface": "#F5F5F5",
|
|
42
|
+
"muted": "#6B7280",
|
|
43
|
+
"muted-foreground": "#9CA3AF",
|
|
44
|
+
"border": "#E5E7EB",
|
|
45
|
+
"destructive": "#EF4444",
|
|
46
|
+
"destructive-foreground": "#FFFFFF"
|
|
47
|
+
},
|
|
48
|
+
"radius": "rounded-lg",
|
|
49
|
+
"shadow": "shadow-sm",
|
|
50
|
+
"spacing": {
|
|
51
|
+
"tight": "2",
|
|
52
|
+
"normal": "4",
|
|
53
|
+
"loose": "6"
|
|
54
|
+
},
|
|
55
|
+
"typography": {
|
|
56
|
+
"family": "font-sans",
|
|
57
|
+
"heading": "font-semibold tracking-tight",
|
|
58
|
+
"body": "font-normal"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"personality": {
|
|
62
|
+
"corners": "rounded",
|
|
63
|
+
"depth": "subtle-shadows",
|
|
64
|
+
"density": "comfortable"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
4. **Generate `.claude/component-recipes/`** directory with recipes for each component type:
|
|
70
|
+
- button.md, card.md, input.md, modal.md, select.md
|
|
71
|
+
- checkbox.md, radio.md, badge.md, alert.md, avatar.md
|
|
72
|
+
- tooltip.md, table.md, tabs.md, accordion.md, dialog.md, toast.md
|
|
73
|
+
|
|
74
|
+
Each recipe should reference `{tokens.*}` from the config and follow the aesthetic choices.
|
|
75
|
+
|
|
76
|
+
5. **Ask about component-harness**: "Want me to scaffold the visual component-harness for previewing?"
|
|
77
|
+
|
|
78
|
+
## Recipe Template
|
|
79
|
+
|
|
80
|
+
When generating each recipe, follow this structure:
|
|
81
|
+
```markdown
|
|
82
|
+
# [Component] Component Recipe
|
|
83
|
+
|
|
84
|
+
## Structure
|
|
85
|
+
- HTML element to use
|
|
86
|
+
- Supported variants
|
|
87
|
+
- Supported sizes
|
|
88
|
+
- Required states (loading, disabled, etc.)
|
|
89
|
+
|
|
90
|
+
## Tailwind Classes
|
|
91
|
+
- Base: [base classes that apply to all variants]
|
|
92
|
+
- [Variant]: [classes for this variant using {tokens.*} references]
|
|
93
|
+
- Sizes: [size-specific classes]
|
|
94
|
+
- States: [hover, focus, disabled classes]
|
|
95
|
+
|
|
96
|
+
## Props Interface
|
|
97
|
+
- variant: [list of variants]
|
|
98
|
+
- size: [list of sizes]
|
|
99
|
+
- [other props]
|
|
100
|
+
|
|
101
|
+
## Do
|
|
102
|
+
- [best practices]
|
|
103
|
+
|
|
104
|
+
## Don't
|
|
105
|
+
- [anti-patterns]
|
|
106
|
+
|
|
107
|
+
## Example
|
|
108
|
+
[code example]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
$ARGUMENTS
|