@hustle-together/api-dev-tools 3.6.5 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5307 -258
- package/bin/cli.js +348 -20
- package/commands/README.md +459 -71
- package/commands/hustle-api-continue.md +158 -0
- package/commands/{api-create.md → hustle-api-create.md} +22 -2
- package/commands/{api-env.md → hustle-api-env.md} +4 -4
- package/commands/{api-interview.md → hustle-api-interview.md} +1 -1
- package/commands/{api-research.md → hustle-api-research.md} +3 -3
- package/commands/hustle-api-sessions.md +149 -0
- package/commands/{api-status.md → hustle-api-status.md} +16 -16
- package/commands/{api-verify.md → hustle-api-verify.md} +2 -2
- package/commands/hustle-combine.md +763 -0
- package/commands/hustle-ui-create.md +825 -0
- package/hooks/api-workflow-check.py +385 -19
- package/hooks/cache-research.py +337 -0
- package/hooks/check-playwright-setup.py +103 -0
- package/hooks/check-storybook-setup.py +81 -0
- package/hooks/detect-interruption.py +165 -0
- package/hooks/enforce-brand-guide.py +131 -0
- package/hooks/enforce-documentation.py +60 -8
- package/hooks/enforce-freshness.py +184 -0
- package/hooks/enforce-questions-sourced.py +146 -0
- package/hooks/enforce-schema-from-interview.py +248 -0
- package/hooks/enforce-ui-disambiguation.py +108 -0
- package/hooks/enforce-ui-interview.py +130 -0
- package/hooks/generate-manifest-entry.py +981 -0
- package/hooks/session-logger.py +297 -0
- package/hooks/session-startup.py +65 -10
- package/hooks/track-scope-coverage.py +220 -0
- package/hooks/track-tool-use.py +81 -1
- package/hooks/update-api-showcase.py +149 -0
- package/hooks/update-registry.py +352 -0
- package/hooks/update-ui-showcase.py +148 -0
- package/package.json +8 -2
- package/templates/BRAND_GUIDE.md +299 -0
- package/templates/CLAUDE-SECTION.md +56 -24
- package/templates/SPEC.json +640 -0
- package/templates/api-dev-state.json +179 -161
- package/templates/api-showcase/APICard.tsx +153 -0
- package/templates/api-showcase/APIModal.tsx +375 -0
- package/templates/api-showcase/APIShowcase.tsx +231 -0
- package/templates/api-showcase/APITester.tsx +522 -0
- package/templates/api-showcase/page.tsx +41 -0
- package/templates/component/Component.stories.tsx +172 -0
- package/templates/component/Component.test.tsx +237 -0
- package/templates/component/Component.tsx +86 -0
- package/templates/component/Component.types.ts +55 -0
- package/templates/component/index.ts +15 -0
- package/templates/dev-tools/_components/DevToolsLanding.tsx +320 -0
- package/templates/dev-tools/page.tsx +10 -0
- package/templates/page/page.e2e.test.ts +218 -0
- package/templates/page/page.tsx +42 -0
- package/templates/performance-budgets.json +58 -0
- package/templates/registry.json +13 -0
- package/templates/settings.json +74 -0
- package/templates/shared/HeroHeader.tsx +261 -0
- package/templates/shared/index.ts +1 -0
- package/templates/ui-showcase/PreviewCard.tsx +315 -0
- package/templates/ui-showcase/PreviewModal.tsx +676 -0
- package/templates/ui-showcase/UIShowcase.tsx +262 -0
- package/templates/ui-showcase/page.tsx +26 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create UI components or pages with 13-phase interview-driven workflow
|
|
3
|
+
argument-hint: [component-name]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hustle UI Create
|
|
7
|
+
|
|
8
|
+
**Version:** 3.9.0
|
|
9
|
+
**13-phase workflow for creating UI components and pages**
|
|
10
|
+
|
|
11
|
+
You are creating a UI element using the Hustle Together interview-driven workflow.
|
|
12
|
+
|
|
13
|
+
## Pre-Flight Check
|
|
14
|
+
|
|
15
|
+
Before starting, verify state file exists:
|
|
16
|
+
```bash
|
|
17
|
+
cat .claude/api-dev-state.json 2>/dev/null || echo "Creating new state file"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Mode Selection
|
|
21
|
+
|
|
22
|
+
**MANDATORY: Ask user before proceeding:**
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
What would you like to create?
|
|
26
|
+
|
|
27
|
+
A) Component - Isolated reusable UI component
|
|
28
|
+
- Creates component in src/components/[Name]/
|
|
29
|
+
- Adds to UI Showcase page
|
|
30
|
+
- Tests via Storybook + Vitest
|
|
31
|
+
|
|
32
|
+
B) Page - Full page that may use existing components
|
|
33
|
+
- Creates page in src/app/[name]/
|
|
34
|
+
- Selects components from registry
|
|
35
|
+
- Tests via Playwright E2E
|
|
36
|
+
|
|
37
|
+
Please select A or B:
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Wait for user response. Do not proceed without explicit selection.**
|
|
41
|
+
|
|
42
|
+
Set `mode` based on response: "component" or "page"
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# Component Mode (13 Phases)
|
|
47
|
+
|
|
48
|
+
## Phase 1: DISAMBIGUATION
|
|
49
|
+
|
|
50
|
+
**Goal:** Clarify component type and scope
|
|
51
|
+
|
|
52
|
+
Ask the user:
|
|
53
|
+
```
|
|
54
|
+
Phase 1: DISAMBIGUATION
|
|
55
|
+
|
|
56
|
+
What type of component is this?
|
|
57
|
+
|
|
58
|
+
A) Atom - Basic building block (Button, Input, Icon, Badge)
|
|
59
|
+
B) Molecule - Simple group of atoms (FormField, Card, SearchBar)
|
|
60
|
+
C) Organism - Complex section (Header, Sidebar, DataTable, Modal)
|
|
61
|
+
|
|
62
|
+
Please select A, B, or C:
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Wait for user response.**
|
|
66
|
+
|
|
67
|
+
Update state:
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"workflow": "ui-create-component",
|
|
71
|
+
"element_name": "[component-name]",
|
|
72
|
+
"element_type": "component",
|
|
73
|
+
"ui_config": {
|
|
74
|
+
"component_type": "[atom|molecule|organism]"
|
|
75
|
+
},
|
|
76
|
+
"phases": {
|
|
77
|
+
"disambiguation": {
|
|
78
|
+
"status": "complete",
|
|
79
|
+
"component_type": "[selected]"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Phase 2: SCOPE
|
|
88
|
+
|
|
89
|
+
**Goal:** Confirm understanding of component purpose
|
|
90
|
+
|
|
91
|
+
Based on the component name and type, present your understanding:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Phase 2: SCOPE CONFIRMATION
|
|
95
|
+
|
|
96
|
+
Based on your input, here's my understanding:
|
|
97
|
+
|
|
98
|
+
Component: [Name]
|
|
99
|
+
Type: [Atom/Molecule/Organism]
|
|
100
|
+
Purpose: [Your understanding of what this component does]
|
|
101
|
+
|
|
102
|
+
Expected Features:
|
|
103
|
+
- [Feature 1]
|
|
104
|
+
- [Feature 2]
|
|
105
|
+
- [Feature 3]
|
|
106
|
+
|
|
107
|
+
Does this match your expectations?
|
|
108
|
+
A) Yes, proceed
|
|
109
|
+
B) No, let me clarify
|
|
110
|
+
|
|
111
|
+
Please select A or B:
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Wait for user response. Loop back if B selected.**
|
|
115
|
+
|
|
116
|
+
Update state with `phases.scope.status = "complete"`
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Phase 3: DESIGN RESEARCH
|
|
121
|
+
|
|
122
|
+
**Goal:** Research design patterns AND check brand guide
|
|
123
|
+
|
|
124
|
+
### Step 3a: Brand Guide Check
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Phase 3: DESIGN RESEARCH
|
|
128
|
+
|
|
129
|
+
I found your brand guide at .claude/BRAND_GUIDE.md
|
|
130
|
+
|
|
131
|
+
If you need to update your brand guide, NOW is the time!
|
|
132
|
+
1. Open .claude/BRAND_GUIDE.md
|
|
133
|
+
2. Make your changes
|
|
134
|
+
3. Save the file
|
|
135
|
+
4. Then select option A below
|
|
136
|
+
|
|
137
|
+
Should I use the project brand guide?
|
|
138
|
+
A) Yes, use brand guide (default) - I will apply these styles
|
|
139
|
+
B) No, use different reference [provide URL or description]
|
|
140
|
+
|
|
141
|
+
Please select A or B:
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Wait for user response.**
|
|
145
|
+
|
|
146
|
+
If A: Read `.claude/BRAND_GUIDE.md` and note key values (colors, spacing, border-radius)
|
|
147
|
+
If B: Ask for URL or description
|
|
148
|
+
|
|
149
|
+
### Step 3b: Design Pattern Research
|
|
150
|
+
|
|
151
|
+
Perform 2-3 targeted searches:
|
|
152
|
+
1. `[component-name] component best practices accessibility`
|
|
153
|
+
2. `shadcn [component-name] implementation`
|
|
154
|
+
3. `radix [component-name] primitive`
|
|
155
|
+
|
|
156
|
+
Use Context7 for ShadCN/Radix documentation.
|
|
157
|
+
|
|
158
|
+
Document findings in state:
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"phases": {
|
|
162
|
+
"design_research": {
|
|
163
|
+
"status": "complete",
|
|
164
|
+
"brand_guide_applied": true,
|
|
165
|
+
"sources": ["source1", "source2"]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Phase 4: INTERVIEW
|
|
174
|
+
|
|
175
|
+
**Goal:** Deep dive into component requirements
|
|
176
|
+
|
|
177
|
+
Ask 5-10 questions based on research findings. Questions should be GENERATED from research, not template.
|
|
178
|
+
|
|
179
|
+
**Example questions (customize based on research):**
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
Phase 4: INTERVIEW
|
|
183
|
+
|
|
184
|
+
Based on my research, I have some questions about your [Component]:
|
|
185
|
+
|
|
186
|
+
Q1: Design System Base
|
|
187
|
+
Which design system should I use?
|
|
188
|
+
A) ShadCN - Use shadcn/ui components
|
|
189
|
+
B) Radix - Use Radix primitives directly
|
|
190
|
+
C) Custom - Build from scratch
|
|
191
|
+
|
|
192
|
+
Q2: Variants
|
|
193
|
+
Which visual variants does this component need? (select all)
|
|
194
|
+
[ ] Size (sm, md, lg)
|
|
195
|
+
[ ] Color (primary, secondary, destructive)
|
|
196
|
+
[ ] State (disabled, loading, error)
|
|
197
|
+
|
|
198
|
+
Q3: Accessibility Level
|
|
199
|
+
What accessibility standard should we meet?
|
|
200
|
+
A) WCAG 2.1 AA (standard)
|
|
201
|
+
B) WCAG 2.1 AAA (enhanced)
|
|
202
|
+
C) Basic (keyboard nav + aria labels only)
|
|
203
|
+
|
|
204
|
+
Q4: [Research-derived question about specific feature]
|
|
205
|
+
|
|
206
|
+
Q5: [Research-derived question about specific feature]
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Wait for all answers before proceeding.**
|
|
210
|
+
|
|
211
|
+
Store all decisions in state:
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"phases": {
|
|
215
|
+
"interview": {
|
|
216
|
+
"status": "complete",
|
|
217
|
+
"decisions": {
|
|
218
|
+
"design_system": "shadcn",
|
|
219
|
+
"variants": ["size", "color"],
|
|
220
|
+
"accessibility": "wcag2aa"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Phase 5: COMPONENT ANALYSIS
|
|
230
|
+
|
|
231
|
+
**Goal:** Check for existing ShadCN components to use
|
|
232
|
+
|
|
233
|
+
If design system is ShadCN, check `src/components/ui/`:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
ls -la src/components/ui/ 2>/dev/null || echo "No existing ShadCN components"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
If components found:
|
|
240
|
+
```
|
|
241
|
+
Phase 5: COMPONENT ANALYSIS
|
|
242
|
+
|
|
243
|
+
Existing ShadCN Components Found:
|
|
244
|
+
|
|
245
|
+
src/components/ui/
|
|
246
|
+
├── button.tsx
|
|
247
|
+
├── input.tsx
|
|
248
|
+
├── label.tsx
|
|
249
|
+
└── card.tsx
|
|
250
|
+
|
|
251
|
+
Your [Component] could use: [Input, Label]
|
|
252
|
+
|
|
253
|
+
Would you like to use these existing components?
|
|
254
|
+
A) Yes, use these (recommended)
|
|
255
|
+
B) No, create new ones
|
|
256
|
+
C) Some - let me specify
|
|
257
|
+
|
|
258
|
+
Please select:
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Wait for user response.**
|
|
262
|
+
|
|
263
|
+
Also check registry for custom components:
|
|
264
|
+
```bash
|
|
265
|
+
cat .claude/registry.json | jq '.components'
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Update state with dependencies list.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Phase 6: PROPS SCHEMA
|
|
273
|
+
|
|
274
|
+
**Goal:** Create TypeScript interface from interview answers
|
|
275
|
+
|
|
276
|
+
Based on interview decisions, create props interface:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// src/components/[Name]/[Name].types.ts
|
|
280
|
+
|
|
281
|
+
export interface [Name]Props {
|
|
282
|
+
/** Visual variant */
|
|
283
|
+
variant?: 'primary' | 'secondary' | 'destructive';
|
|
284
|
+
|
|
285
|
+
/** Size variant */
|
|
286
|
+
size?: 'sm' | 'md' | 'lg';
|
|
287
|
+
|
|
288
|
+
/** Loading state */
|
|
289
|
+
loading?: boolean;
|
|
290
|
+
|
|
291
|
+
/** Disabled state */
|
|
292
|
+
disabled?: boolean;
|
|
293
|
+
|
|
294
|
+
/** Children content */
|
|
295
|
+
children: React.ReactNode;
|
|
296
|
+
|
|
297
|
+
/** Additional class names */
|
|
298
|
+
className?: string;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Present to user:
|
|
303
|
+
```
|
|
304
|
+
Phase 6: PROPS SCHEMA
|
|
305
|
+
|
|
306
|
+
Here's the TypeScript interface I've created:
|
|
307
|
+
|
|
308
|
+
[Show interface]
|
|
309
|
+
|
|
310
|
+
Does this schema look correct?
|
|
311
|
+
A) Yes, proceed
|
|
312
|
+
B) No, needs changes [specify]
|
|
313
|
+
|
|
314
|
+
Please select:
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Wait for approval before proceeding.**
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Phase 7: ENVIRONMENT
|
|
322
|
+
|
|
323
|
+
**Goal:** Verify required packages and Storybook setup
|
|
324
|
+
|
|
325
|
+
Check for required packages:
|
|
326
|
+
```bash
|
|
327
|
+
cat package.json | jq '.dependencies, .devDependencies' | grep -E "radix|shadcn|class-variance|clsx|tailwind"
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Check Storybook:
|
|
331
|
+
```bash
|
|
332
|
+
ls -la .storybook/ 2>/dev/null || echo "Storybook not configured"
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
If Storybook not found:
|
|
336
|
+
```
|
|
337
|
+
Phase 7: ENVIRONMENT CHECK
|
|
338
|
+
|
|
339
|
+
Storybook is not configured in this project.
|
|
340
|
+
|
|
341
|
+
Would you like me to initialize Storybook?
|
|
342
|
+
A) Yes, run: npx storybook@latest init
|
|
343
|
+
B) No, skip Storybook stories
|
|
344
|
+
|
|
345
|
+
Please select:
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Report status:
|
|
349
|
+
```
|
|
350
|
+
Environment Check:
|
|
351
|
+
Packages: [radix, class-variance-authority, clsx]
|
|
352
|
+
Storybook: [Configured/Not configured]
|
|
353
|
+
Tailwind: [Found/Not found]
|
|
354
|
+
|
|
355
|
+
Ready to proceed with TDD?
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Phase 8: TDD RED
|
|
361
|
+
|
|
362
|
+
**Goal:** Write failing tests and Storybook stories
|
|
363
|
+
|
|
364
|
+
### Create Test File
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
// src/components/[Name]/__tests__/[Name].test.tsx
|
|
368
|
+
|
|
369
|
+
import { render, screen } from '@testing-library/react';
|
|
370
|
+
import { describe, it, expect } from 'vitest';
|
|
371
|
+
import { [Name] } from '../[Name]';
|
|
372
|
+
|
|
373
|
+
describe('[Name]', () => {
|
|
374
|
+
it('renders children correctly', () => {
|
|
375
|
+
render(<[Name]>Test Content</[Name]>);
|
|
376
|
+
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it('applies variant classes', () => {
|
|
380
|
+
const { container } = render(<[Name] variant="primary">Test</[Name]>);
|
|
381
|
+
expect(container.firstChild).toHaveClass('...');
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('handles disabled state', () => {
|
|
385
|
+
render(<[Name] disabled>Test</[Name]>);
|
|
386
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('shows loading indicator when loading', () => {
|
|
390
|
+
render(<[Name] loading>Test</[Name]>);
|
|
391
|
+
expect(screen.getByRole('button')).toHaveAttribute('aria-busy', 'true');
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Create Storybook Story
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
// src/components/[Name]/[Name].stories.tsx
|
|
400
|
+
|
|
401
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
402
|
+
import { [Name] } from './[Name]';
|
|
403
|
+
|
|
404
|
+
const meta: Meta<typeof [Name]> = {
|
|
405
|
+
title: 'Components/[Name]',
|
|
406
|
+
component: [Name],
|
|
407
|
+
parameters: { layout: 'centered' },
|
|
408
|
+
tags: ['autodocs'],
|
|
409
|
+
argTypes: {
|
|
410
|
+
variant: { control: 'select', options: ['primary', 'secondary', 'destructive'] },
|
|
411
|
+
size: { control: 'select', options: ['sm', 'md', 'lg'] },
|
|
412
|
+
loading: { control: 'boolean' },
|
|
413
|
+
disabled: { control: 'boolean' },
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
export default meta;
|
|
418
|
+
type Story = StoryObj<typeof meta>;
|
|
419
|
+
|
|
420
|
+
export const Primary: Story = {
|
|
421
|
+
args: { variant: 'primary', children: 'Primary [Name]' },
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
export const Secondary: Story = {
|
|
425
|
+
args: { variant: 'secondary', children: 'Secondary [Name]' },
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
export const Loading: Story = {
|
|
429
|
+
args: { loading: true, children: 'Loading...' },
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
export const Disabled: Story = {
|
|
433
|
+
args: { disabled: true, children: 'Disabled' },
|
|
434
|
+
};
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Run Tests (Expect Failure)
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
pnpm test src/components/[Name]
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**Tests MUST fail at this point (component doesn't exist yet).**
|
|
444
|
+
|
|
445
|
+
Update state: `phases.tdd_red.status = "complete"`
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Phase 9: TDD GREEN
|
|
450
|
+
|
|
451
|
+
**Goal:** Implement component to pass tests
|
|
452
|
+
|
|
453
|
+
### Create Component Files
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
// src/components/[Name]/[Name].tsx
|
|
457
|
+
|
|
458
|
+
import * as React from 'react';
|
|
459
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
460
|
+
import { cn } from '@/lib/utils';
|
|
461
|
+
import { [Name]Props } from './[Name].types';
|
|
462
|
+
|
|
463
|
+
const [name]Variants = cva(
|
|
464
|
+
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
|
465
|
+
{
|
|
466
|
+
variants: {
|
|
467
|
+
variant: {
|
|
468
|
+
primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
469
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
470
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
471
|
+
},
|
|
472
|
+
size: {
|
|
473
|
+
sm: 'h-8 px-3 text-sm',
|
|
474
|
+
md: 'h-10 px-4 text-base',
|
|
475
|
+
lg: 'h-12 px-6 text-lg',
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
defaultVariants: {
|
|
479
|
+
variant: 'primary',
|
|
480
|
+
size: 'md',
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
export function [Name]({
|
|
486
|
+
variant,
|
|
487
|
+
size,
|
|
488
|
+
loading,
|
|
489
|
+
disabled,
|
|
490
|
+
className,
|
|
491
|
+
children,
|
|
492
|
+
...props
|
|
493
|
+
}: [Name]Props) {
|
|
494
|
+
return (
|
|
495
|
+
<button
|
|
496
|
+
className={cn([name]Variants({ variant, size }), className)}
|
|
497
|
+
disabled={disabled || loading}
|
|
498
|
+
aria-busy={loading}
|
|
499
|
+
{...props}
|
|
500
|
+
>
|
|
501
|
+
{loading && <Spinner className="mr-2" />}
|
|
502
|
+
{children}
|
|
503
|
+
</button>
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Create Barrel Export
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
// src/components/[Name]/index.ts
|
|
512
|
+
|
|
513
|
+
export { [Name] } from './[Name]';
|
|
514
|
+
export type { [Name]Props } from './[Name].types';
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Run Tests (Expect Pass)
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
pnpm test src/components/[Name]
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**All tests MUST pass before proceeding.**
|
|
524
|
+
|
|
525
|
+
Update state: `phases.tdd_green.status = "complete"`
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## Phase 10: VERIFY (4-STEP MANDATORY)
|
|
530
|
+
|
|
531
|
+
**Goal:** Comprehensive verification across 4 dimensions
|
|
532
|
+
|
|
533
|
+
### Step 1: Responsive Check
|
|
534
|
+
|
|
535
|
+
Run Storybook at different viewports or use Playwright:
|
|
536
|
+
|
|
537
|
+
```
|
|
538
|
+
Step 1: Responsive Check
|
|
539
|
+
|
|
540
|
+
Desktop (1920px): [Checking...]
|
|
541
|
+
Tablet (768px): [Checking...]
|
|
542
|
+
Mobile (375px): [Checking...]
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
Verify component renders correctly at all sizes.
|
|
546
|
+
|
|
547
|
+
### Step 2: Brand Guide Match
|
|
548
|
+
|
|
549
|
+
Compare implementation to `.claude/BRAND_GUIDE.md`:
|
|
550
|
+
|
|
551
|
+
```
|
|
552
|
+
Step 2: Brand Guide Match
|
|
553
|
+
|
|
554
|
+
Colors: [Matches brand guide]
|
|
555
|
+
Typography: [Matches brand guide]
|
|
556
|
+
Spacing: [Matches brand guide]
|
|
557
|
+
Border Radius: [Matches brand guide]
|
|
558
|
+
Focus Ring: [Matches brand guide]
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Step 3: All Tests Passed
|
|
562
|
+
|
|
563
|
+
```
|
|
564
|
+
Step 3: Test Results
|
|
565
|
+
|
|
566
|
+
Unit tests: [X/X passed]
|
|
567
|
+
Storybook stories: [X/X render]
|
|
568
|
+
A11y audit: [WCAG 2.1 AA compliant]
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Run accessibility audit:
|
|
572
|
+
```bash
|
|
573
|
+
pnpm dlx @axe-core/cli http://localhost:6006/iframe.html?id=components-[name]--primary
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Step 4: Performance Metrics
|
|
577
|
+
|
|
578
|
+
Log memory and re-renders:
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
Step 4: Performance Metrics
|
|
582
|
+
|
|
583
|
+
Memory usage: [X MB]
|
|
584
|
+
Re-renders on mount: [X]
|
|
585
|
+
Re-renders on change: [X]
|
|
586
|
+
Bundle size impact: [+X KB]
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**Present 4-step results:**
|
|
590
|
+
```
|
|
591
|
+
Phase 10: VERIFICATION (4-Step)
|
|
592
|
+
|
|
593
|
+
Step 1: Responsive Check
|
|
594
|
+
Desktop (1920px) - Renders correctly
|
|
595
|
+
Tablet (768px) - Renders correctly
|
|
596
|
+
Mobile (375px) - Renders correctly
|
|
597
|
+
|
|
598
|
+
Step 2: Brand Guide Match
|
|
599
|
+
Colors match .claude/BRAND_GUIDE.md
|
|
600
|
+
Typography matches
|
|
601
|
+
Spacing matches
|
|
602
|
+
Border radius matches
|
|
603
|
+
|
|
604
|
+
Step 3: All Tests Passed
|
|
605
|
+
Unit tests: 8/8 passed
|
|
606
|
+
Storybook stories: 4/4 render
|
|
607
|
+
A11y audit: WCAG 2.1 AA compliant
|
|
608
|
+
|
|
609
|
+
Step 4: Performance Metrics
|
|
610
|
+
Memory usage: 2.1 MB
|
|
611
|
+
Re-renders on mount: 1 (optimal)
|
|
612
|
+
Re-renders on prop change: 1 (optimal)
|
|
613
|
+
|
|
614
|
+
All 4 checks passed!
|
|
615
|
+
|
|
616
|
+
Any issues to fix?
|
|
617
|
+
A) No, all good - proceed
|
|
618
|
+
B) Yes, need to fix [specify]
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**Wait for user response. Loop back if issues found.**
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## Phase 11: TDD REFACTOR
|
|
626
|
+
|
|
627
|
+
**Goal:** Clean up code while tests pass
|
|
628
|
+
|
|
629
|
+
Refactoring checklist:
|
|
630
|
+
- [ ] Extract repeated logic to custom hooks
|
|
631
|
+
- [ ] Optimize re-renders with useMemo/useCallback if needed
|
|
632
|
+
- [ ] Clean up unused imports
|
|
633
|
+
- [ ] Ensure consistent code style
|
|
634
|
+
- [ ] Add JSDoc comments to exported functions
|
|
635
|
+
|
|
636
|
+
Run tests after each refactor:
|
|
637
|
+
```bash
|
|
638
|
+
pnpm test src/components/[Name]
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Phase 12: DOCUMENTATION
|
|
644
|
+
|
|
645
|
+
**Goal:** Complete all documentation
|
|
646
|
+
|
|
647
|
+
### Storybook Autodocs
|
|
648
|
+
|
|
649
|
+
Ensure `tags: ['autodocs']` is set in story meta.
|
|
650
|
+
|
|
651
|
+
### JSDoc Comments
|
|
652
|
+
|
|
653
|
+
Add to component file:
|
|
654
|
+
```typescript
|
|
655
|
+
/**
|
|
656
|
+
* [Name] component - [Brief description]
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* ```tsx
|
|
660
|
+
* <[Name] variant="primary" size="md">
|
|
661
|
+
* Click me
|
|
662
|
+
* </[Name]>
|
|
663
|
+
* ```
|
|
664
|
+
*/
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Registry Entry
|
|
668
|
+
|
|
669
|
+
Update `.claude/registry.json`:
|
|
670
|
+
```json
|
|
671
|
+
{
|
|
672
|
+
"components": {
|
|
673
|
+
"[name]": {
|
|
674
|
+
"name": "[Name]",
|
|
675
|
+
"description": "[From interview]",
|
|
676
|
+
"file": "src/components/[Name]/[Name].tsx",
|
|
677
|
+
"story": "src/components/[Name]/[Name].stories.tsx",
|
|
678
|
+
"tests": "src/components/[Name]/__tests__/",
|
|
679
|
+
"props_interface": "[Name]Props",
|
|
680
|
+
"variants": ["primary", "secondary"],
|
|
681
|
+
"accessibility": "wcag2aa",
|
|
682
|
+
"responsive": true,
|
|
683
|
+
"status": "complete",
|
|
684
|
+
"created_at": "[date]"
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
Present checklist:
|
|
691
|
+
```
|
|
692
|
+
Phase 12: DOCUMENTATION
|
|
693
|
+
|
|
694
|
+
Storybook autodocs: [Complete]
|
|
695
|
+
JSDoc comments: [Complete]
|
|
696
|
+
Types exported: [Complete]
|
|
697
|
+
Registry updated: [Complete]
|
|
698
|
+
|
|
699
|
+
Documentation complete?
|
|
700
|
+
A) Yes, proceed to completion
|
|
701
|
+
B) No, need changes
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## Phase 13: COMPLETION
|
|
707
|
+
|
|
708
|
+
**Goal:** Final output and continuation prompt
|
|
709
|
+
|
|
710
|
+
### Update UI Showcase
|
|
711
|
+
|
|
712
|
+
If first component, create showcase page. Otherwise, component is auto-added via registry.
|
|
713
|
+
|
|
714
|
+
### Final Output
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
[Name] component complete!
|
|
718
|
+
|
|
719
|
+
Created Files:
|
|
720
|
+
- src/components/[Name]/[Name].tsx
|
|
721
|
+
- src/components/[Name]/[Name].types.ts
|
|
722
|
+
- src/components/[Name]/[Name].stories.tsx
|
|
723
|
+
- src/components/[Name]/__tests__/[Name].test.tsx
|
|
724
|
+
- src/components/[Name]/index.ts
|
|
725
|
+
|
|
726
|
+
Tests: All passed (ran during Phase 8-9)
|
|
727
|
+
A11y: WCAG 2.1 AA compliant
|
|
728
|
+
Brand: Matches .claude/BRAND_GUIDE.md
|
|
729
|
+
|
|
730
|
+
Registry: Added to .claude/registry.json
|
|
731
|
+
|
|
732
|
+
Would you like to create another component or page?
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### Showcase Redirect
|
|
736
|
+
|
|
737
|
+
After successful component/page creation, output:
|
|
738
|
+
|
|
739
|
+
```
|
|
740
|
+
Your [component|page] has been added to the showcase!
|
|
741
|
+
|
|
742
|
+
View it at: http://localhost:3000/ui-showcase
|
|
743
|
+
|
|
744
|
+
Or run `pnpm dev` and navigate to /ui-showcase to:
|
|
745
|
+
- Preview your component with live editing (Sandpack)
|
|
746
|
+
- Test different variants and props
|
|
747
|
+
- View at different viewport sizes
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
For Sandpack live editing, install: `pnpm add @codesandbox/sandpack-react`
|
|
751
|
+
|
|
752
|
+
Update state: `phases.completion.status = "complete"`
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
# Page Mode (13 Phases)
|
|
757
|
+
|
|
758
|
+
Similar flow with these differences:
|
|
759
|
+
|
|
760
|
+
- **Phase 5:** Select components FROM registry instead of checking ShadCN
|
|
761
|
+
- **Phase 6:** Create page data schema (API responses, form data)
|
|
762
|
+
- **Phase 7:** Check API routes and auth configuration
|
|
763
|
+
- **Phase 8:** Write Playwright E2E tests instead of Storybook stories
|
|
764
|
+
- **Phase 9:** Create page in `src/app/[name]/page.tsx`
|
|
765
|
+
- **Phase 10:** Run full Playwright E2E tests
|
|
766
|
+
|
|
767
|
+
See full page mode documentation in `/hustle-ui-create-page.md` (if implementing page mode).
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## State File Structure
|
|
772
|
+
|
|
773
|
+
```json
|
|
774
|
+
{
|
|
775
|
+
"version": "3.9.0",
|
|
776
|
+
"workflow": "ui-create-component",
|
|
777
|
+
"active_element": "[name]",
|
|
778
|
+
"elements": {
|
|
779
|
+
"[name]": {
|
|
780
|
+
"type": "component",
|
|
781
|
+
"status": "in_progress",
|
|
782
|
+
"started_at": "2025-12-12T15:30:00Z",
|
|
783
|
+
"ui_config": {
|
|
784
|
+
"mode": "component",
|
|
785
|
+
"component_type": "atom",
|
|
786
|
+
"design_system": "shadcn",
|
|
787
|
+
"variants": ["size", "color"],
|
|
788
|
+
"accessibility_level": "wcag2aa",
|
|
789
|
+
"use_brand_guide": true
|
|
790
|
+
},
|
|
791
|
+
"phases": {
|
|
792
|
+
"disambiguation": { "status": "complete" },
|
|
793
|
+
"scope": { "status": "complete" },
|
|
794
|
+
"design_research": { "status": "complete", "brand_guide_applied": true },
|
|
795
|
+
"interview": { "status": "complete", "decisions": {} },
|
|
796
|
+
"component_analysis": { "status": "complete", "dependencies": [] },
|
|
797
|
+
"props_schema": { "status": "complete", "schema_file": "..." },
|
|
798
|
+
"environment_check": { "status": "complete" },
|
|
799
|
+
"tdd_red": { "status": "complete", "tests_failed": true },
|
|
800
|
+
"tdd_green": { "status": "complete", "tests_passed": true },
|
|
801
|
+
"verify": { "status": "complete", "four_step_passed": true },
|
|
802
|
+
"tdd_refactor": { "status": "complete" },
|
|
803
|
+
"documentation": { "status": "complete" },
|
|
804
|
+
"completion": { "status": "complete" }
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
## Key Principles
|
|
814
|
+
|
|
815
|
+
1. **ALWAYS ask user** - Never proceed without explicit response
|
|
816
|
+
2. **Brand guide first** - Check and apply before implementation
|
|
817
|
+
3. **ShadCN detection** - Reuse existing components when available
|
|
818
|
+
4. **4-Step verification** - All 4 checks MUST pass
|
|
819
|
+
5. **Tests run automatically** - LLM executes tests, user sees results
|
|
820
|
+
6. **Showcase link guaranteed** - Always output at completion
|
|
821
|
+
|
|
822
|
+
---
|
|
823
|
+
|
|
824
|
+
**Version:** 3.9.0
|
|
825
|
+
**Last Updated:** 2025-12-12
|