ai-flow-dev 1.0.1
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/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +791 -0
- package/dist/cli.js.map +1 -0
- package/dist/fs-utils.d.ts +2 -0
- package/dist/fs-utils.d.ts.map +1 -0
- package/dist/fs-utils.js +46 -0
- package/dist/fs-utils.js.map +1 -0
- package/package.json +71 -0
- package/prompts/backend/flow-dev-feature.md +1318 -0
- package/prompts/backend/flow-dev-fix.md +903 -0
- package/prompts/backend/flow-dev-refactor.md +715 -0
- package/prompts/backend/flow-dev-review.md +401 -0
- package/prompts/backend/flow-dev-work.md +1129 -0
- package/prompts/backend/flow-docs-gen-phase-0.md +1840 -0
- package/prompts/backend/flow-docs-gen-phase-1.md +435 -0
- package/prompts/backend/flow-docs-gen-phase-2.md +460 -0
- package/prompts/backend/flow-docs-gen-phase-3.md +684 -0
- package/prompts/backend/flow-docs-gen-phase-4.md +516 -0
- package/prompts/backend/flow-docs-gen-phase-5.md +637 -0
- package/prompts/backend/flow-docs-gen-phase-6.md +465 -0
- package/prompts/backend/flow-docs-gen-phase-7.md +1207 -0
- package/prompts/backend/flow-docs-gen.md +820 -0
- package/prompts/backend/flow-docs-sync.md +526 -0
- package/prompts/backend/flow-project-init.md +248 -0
- package/prompts/backend/flow-project-roadmap.md +1159 -0
- package/prompts/frontend/flow-docs-gen-phase-0.md +494 -0
- package/prompts/frontend/flow-docs-gen-phase-1.md +449 -0
- package/prompts/frontend/flow-docs-gen-phase-2.md +983 -0
- package/prompts/frontend/flow-docs-gen-phase-3.md +685 -0
- package/prompts/frontend/flow-docs-gen-phase-4.md +480 -0
- package/prompts/frontend/flow-docs-gen-phase-5.md +483 -0
- package/prompts/frontend/flow-docs-gen-phase-6.md +570 -0
- package/prompts/frontend/flow-docs-gen-phase-7.md +582 -0
- package/prompts/frontend/flow-docs-gen.md +413 -0
- package/prompts/frontend/flow-docs-sync.md +561 -0
- package/prompts/mobile/flow-docs-gen-phase-0.md +387 -0
- package/prompts/mobile/flow-docs-gen-phase-1.md +530 -0
- package/prompts/mobile/flow-docs-gen-phase-2.md +584 -0
- package/prompts/mobile/flow-docs-gen-phase-3.md +659 -0
- package/prompts/mobile/flow-docs-gen-phase-4.md +363 -0
- package/prompts/mobile/flow-docs-gen-phase-5.md +369 -0
- package/prompts/mobile/flow-docs-gen-phase-6.md +490 -0
- package/prompts/mobile/flow-docs-gen-phase-7.md +407 -0
- package/prompts/mobile/flow-docs-gen.md +430 -0
- package/prompts/mobile/flow-docs-sync.md +634 -0
- package/templates/backend/.clauderules.template +111 -0
- package/templates/backend/.cursorrules.template +102 -0
- package/templates/backend/.env.example.template +122 -0
- package/templates/backend/README.template.md +200 -0
- package/templates/backend/ai-instructions.template.md +354 -0
- package/templates/backend/copilot-instructions.template.md +160 -0
- package/templates/backend/docs/api.template.md +251 -0
- package/templates/backend/docs/architecture.template.md +612 -0
- package/templates/backend/docs/business-flows.template.md +109 -0
- package/templates/backend/docs/code-standards.template.md +828 -0
- package/templates/backend/docs/contributing.template.md +163 -0
- package/templates/backend/docs/data-model.template.md +416 -0
- package/templates/backend/docs/operations.template.md +591 -0
- package/templates/backend/docs/testing.template.md +762 -0
- package/templates/backend/project-brief.template.md +176 -0
- package/templates/backend/specs/configuration.template.md +133 -0
- package/templates/backend/specs/security.template.md +422 -0
- package/templates/frontend/README.template.md +121 -0
- package/templates/frontend/ai-instructions.template.md +368 -0
- package/templates/frontend/docs/api-integration.template.md +390 -0
- package/templates/frontend/docs/components.template.md +567 -0
- package/templates/frontend/docs/error-handling.template.md +385 -0
- package/templates/frontend/docs/operations.template.md +123 -0
- package/templates/frontend/docs/performance.template.md +140 -0
- package/templates/frontend/docs/pwa.template.md +135 -0
- package/templates/frontend/docs/state-management.template.md +394 -0
- package/templates/frontend/docs/styling.template.md +779 -0
- package/templates/frontend/docs/testing.template.md +736 -0
- package/templates/frontend/project-brief.template.md +55 -0
- package/templates/frontend/specs/accessibility.template.md +111 -0
- package/templates/frontend/specs/configuration.template.md +520 -0
- package/templates/frontend/specs/security.template.md +197 -0
- package/templates/fullstack/README.template.md +282 -0
- package/templates/fullstack/ai-instructions.template.md +487 -0
- package/templates/fullstack/project-brief.template.md +197 -0
- package/templates/fullstack/specs/configuration.template.md +380 -0
- package/templates/mobile/AGENT.template.md +251 -0
- package/templates/mobile/README.template.md +195 -0
- package/templates/mobile/ai-instructions.template.md +221 -0
- package/templates/mobile/docs/app-store.template.md +163 -0
- package/templates/mobile/docs/architecture.template.md +100 -0
- package/templates/mobile/docs/native-features.template.md +137 -0
- package/templates/mobile/docs/navigation.template.md +81 -0
- package/templates/mobile/docs/offline-strategy.template.md +90 -0
- package/templates/mobile/docs/permissions.template.md +70 -0
- package/templates/mobile/docs/state-management.template.md +116 -0
- package/templates/mobile/docs/testing.template.md +146 -0
- package/templates/mobile/project-brief.template.md +97 -0
- package/templates/mobile/specs/build-configuration.template.md +116 -0
- package/templates/mobile/specs/deployment.template.md +114 -0
- package/templates/shared/AGENT.template.md +252 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
# Component Architecture
|
|
2
|
+
|
|
3
|
+
> Component organization, patterns, and best practices for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📐 Component Pattern
|
|
8
|
+
|
|
9
|
+
**Pattern:** {{COMPONENT_PATTERN}}
|
|
10
|
+
|
|
11
|
+
{{COMPONENT_PATTERN_DESCRIPTION}}
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🏗️ Component Hierarchy
|
|
16
|
+
|
|
17
|
+
### Atomic Design (if using)
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Atoms (primitives)
|
|
21
|
+
↓
|
|
22
|
+
Molecules (simple combinations)
|
|
23
|
+
↓
|
|
24
|
+
Organisms (complex components)
|
|
25
|
+
↓
|
|
26
|
+
Templates (page layouts)
|
|
27
|
+
↓
|
|
28
|
+
Pages (instances with real data)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Feature-Based (if using)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
features/
|
|
35
|
+
auth/
|
|
36
|
+
components/
|
|
37
|
+
hooks/
|
|
38
|
+
services/
|
|
39
|
+
dashboard/
|
|
40
|
+
components/
|
|
41
|
+
hooks/
|
|
42
|
+
services/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 📁 File Structure
|
|
48
|
+
|
|
49
|
+
### Component File Organization
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
{{COMPONENT_FILE_STRUCTURE}}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Example:**
|
|
56
|
+
```
|
|
57
|
+
src/
|
|
58
|
+
├── components/ # Shared components
|
|
59
|
+
│ ├── atoms/ # Basic building blocks
|
|
60
|
+
│ │ ├── Button/
|
|
61
|
+
│ │ │ ├── Button.tsx
|
|
62
|
+
│ │ │ ├── Button.module.css (or .scss, .styled.ts)
|
|
63
|
+
│ │ │ ├── Button.test.tsx
|
|
64
|
+
│ │ │ ├── Button.stories.tsx (optional)
|
|
65
|
+
│ │ │ └── index.ts
|
|
66
|
+
│ │ └── Input/
|
|
67
|
+
│ ├── molecules/ # Simple composites
|
|
68
|
+
│ │ ├── SearchBar/
|
|
69
|
+
│ │ └── FormField/
|
|
70
|
+
│ ├── organisms/ # Complex components
|
|
71
|
+
│ │ ├── Header/
|
|
72
|
+
│ │ ├── UserCard/
|
|
73
|
+
│ │ └── DataTable/
|
|
74
|
+
│ └── templates/ # Page layouts
|
|
75
|
+
│ ├── MainLayout/
|
|
76
|
+
│ └── AuthLayout/
|
|
77
|
+
├── pages/ # Route components
|
|
78
|
+
│ ├── Home/
|
|
79
|
+
│ ├── Dashboard/
|
|
80
|
+
│ └── Profile/
|
|
81
|
+
├── features/ # Feature-specific code
|
|
82
|
+
│ ├── auth/
|
|
83
|
+
│ └── posts/
|
|
84
|
+
├── hooks/ # Custom hooks/composables
|
|
85
|
+
├── services/ # API services
|
|
86
|
+
├── utils/ # Utility functions
|
|
87
|
+
└── types/ # TypeScript types
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 🧩 Component Types
|
|
93
|
+
|
|
94
|
+
### 1. Presentational Components (Atoms/Molecules)
|
|
95
|
+
|
|
96
|
+
**Purpose:** Pure UI components, no business logic
|
|
97
|
+
|
|
98
|
+
**Characteristics:**
|
|
99
|
+
- Receive all data via props
|
|
100
|
+
- No side effects or API calls
|
|
101
|
+
- Highly reusable
|
|
102
|
+
- Easy to test
|
|
103
|
+
|
|
104
|
+
**Example ({{UI_FRAMEWORK}}):**
|
|
105
|
+
```typescript
|
|
106
|
+
// Button.tsx
|
|
107
|
+
interface ButtonProps {
|
|
108
|
+
children: React.ReactNode;
|
|
109
|
+
variant?: 'primary' | 'secondary' | 'danger';
|
|
110
|
+
size?: 'sm' | 'md' | 'lg';
|
|
111
|
+
disabled?: boolean;
|
|
112
|
+
onClick?: () => void;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const Button: React.FC<ButtonProps> = ({
|
|
116
|
+
children,
|
|
117
|
+
variant = 'primary',
|
|
118
|
+
size = 'md',
|
|
119
|
+
disabled = false,
|
|
120
|
+
onClick
|
|
121
|
+
}) => {
|
|
122
|
+
return (
|
|
123
|
+
<button
|
|
124
|
+
className={`btn btn-${variant} btn-${size}`}
|
|
125
|
+
disabled={disabled}
|
|
126
|
+
onClick={onClick}
|
|
127
|
+
>
|
|
128
|
+
{children}
|
|
129
|
+
</button>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 2. Container Components (Organisms/Pages)
|
|
135
|
+
|
|
136
|
+
**Purpose:** Handle logic, data fetching, state management
|
|
137
|
+
|
|
138
|
+
**Characteristics:**
|
|
139
|
+
- Fetch data from APIs
|
|
140
|
+
- Manage local state
|
|
141
|
+
- Coordinate child components
|
|
142
|
+
- Handle business logic
|
|
143
|
+
|
|
144
|
+
**Example ({{UI_FRAMEWORK}}):**
|
|
145
|
+
```typescript
|
|
146
|
+
// UserDashboard.tsx
|
|
147
|
+
export const UserDashboard: React.FC = () => {
|
|
148
|
+
const { data, isLoading, error } = useUserData();
|
|
149
|
+
const { updateProfile } = useUpdateProfile();
|
|
150
|
+
|
|
151
|
+
if (isLoading) return <LoadingSpinner />;
|
|
152
|
+
if (error) return <ErrorMessage error={error} />;
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<DashboardLayout>
|
|
156
|
+
<UserProfile user={data.user} />
|
|
157
|
+
<ActivityFeed activities={data.activities} />
|
|
158
|
+
<StatsOverview stats={data.stats} />
|
|
159
|
+
</DashboardLayout>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 3. Layout Components (Templates)
|
|
165
|
+
|
|
166
|
+
**Purpose:** Define page structure and composition
|
|
167
|
+
|
|
168
|
+
**Characteristics:**
|
|
169
|
+
- Provide slots for content
|
|
170
|
+
- Handle responsive layout
|
|
171
|
+
- Manage navigation structure
|
|
172
|
+
|
|
173
|
+
**Example ({{UI_FRAMEWORK}}):**
|
|
174
|
+
```typescript
|
|
175
|
+
// MainLayout.tsx
|
|
176
|
+
interface MainLayoutProps {
|
|
177
|
+
children: React.ReactNode;
|
|
178
|
+
sidebar?: React.ReactNode;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const MainLayout: React.FC<MainLayoutProps> = ({
|
|
182
|
+
children,
|
|
183
|
+
sidebar
|
|
184
|
+
}) => {
|
|
185
|
+
return (
|
|
186
|
+
<div className="main-layout">
|
|
187
|
+
<Header />
|
|
188
|
+
<div className="content-wrapper">
|
|
189
|
+
{sidebar && <Sidebar>{sidebar}</Sidebar>}
|
|
190
|
+
<main className="main-content">
|
|
191
|
+
{children}
|
|
192
|
+
</main>
|
|
193
|
+
</div>
|
|
194
|
+
<Footer />
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 🎯 Component Design Principles
|
|
203
|
+
|
|
204
|
+
### 1. Single Responsibility
|
|
205
|
+
|
|
206
|
+
Each component should do **one thing well**.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// ❌ Bad - Too many responsibilities
|
|
210
|
+
const UserDashboard = () => {
|
|
211
|
+
// Fetches data, handles auth, renders UI, manages forms
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// ✅ Good - Separated concerns
|
|
215
|
+
const UserDashboard = () => {
|
|
216
|
+
const user = useAuth();
|
|
217
|
+
const data = useUserData(user.id);
|
|
218
|
+
|
|
219
|
+
return <DashboardView data={data} />;
|
|
220
|
+
};
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 2. Composition Over Inheritance
|
|
224
|
+
|
|
225
|
+
Build complex UIs by composing simple components.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// ✅ Composition
|
|
229
|
+
<Card>
|
|
230
|
+
<CardHeader>
|
|
231
|
+
<CardTitle>User Profile</CardTitle>
|
|
232
|
+
</CardHeader>
|
|
233
|
+
<CardContent>
|
|
234
|
+
<UserInfo user={user} />
|
|
235
|
+
</CardContent>
|
|
236
|
+
</Card>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### 3. Props Over Context
|
|
240
|
+
|
|
241
|
+
Use props for explicit data flow, context for truly global data.
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// ✅ Props for component-specific data
|
|
245
|
+
<UserProfile user={user} onSave={handleSave} />
|
|
246
|
+
|
|
247
|
+
// ✅ Context for global app state
|
|
248
|
+
const theme = useTheme();
|
|
249
|
+
const auth = useAuth();
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 4. Keep It Simple
|
|
253
|
+
|
|
254
|
+
Avoid premature abstraction. Extract only when pattern emerges 3+ times.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 🔧 Component Patterns
|
|
259
|
+
|
|
260
|
+
### Pattern: Compound Components
|
|
261
|
+
|
|
262
|
+
Allow flexible composition while maintaining internal logic.
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// Tabs.tsx
|
|
266
|
+
export const Tabs = ({ children, defaultTab }) => {
|
|
267
|
+
const [activeTab, setActiveTab] = useState(defaultTab);
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
|
|
271
|
+
<div className="tabs">{children}</div>
|
|
272
|
+
</TabsContext.Provider>
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
Tabs.List = ({ children }) => <div className="tabs-list">{children}</div>;
|
|
277
|
+
Tabs.Tab = ({ id, children }) => {
|
|
278
|
+
const { activeTab, setActiveTab } = useTabsContext();
|
|
279
|
+
return (
|
|
280
|
+
<button
|
|
281
|
+
className={activeTab === id ? 'active' : ''}
|
|
282
|
+
onClick={() => setActiveTab(id)}
|
|
283
|
+
>
|
|
284
|
+
{children}
|
|
285
|
+
</button>
|
|
286
|
+
);
|
|
287
|
+
};
|
|
288
|
+
Tabs.Panel = ({ id, children }) => {
|
|
289
|
+
const { activeTab } = useTabsContext();
|
|
290
|
+
return activeTab === id ? <div>{children}</div> : null;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// Usage
|
|
294
|
+
<Tabs defaultTab="profile">
|
|
295
|
+
<Tabs.List>
|
|
296
|
+
<Tabs.Tab id="profile">Profile</Tabs.Tab>
|
|
297
|
+
<Tabs.Tab id="settings">Settings</Tabs.Tab>
|
|
298
|
+
</Tabs.List>
|
|
299
|
+
<Tabs.Panel id="profile"><ProfileForm /></Tabs.Panel>
|
|
300
|
+
<Tabs.Panel id="settings"><SettingsForm /></Tabs.Panel>
|
|
301
|
+
</Tabs>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Pattern: Render Props
|
|
305
|
+
|
|
306
|
+
Share logic with flexible rendering.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// DataLoader.tsx
|
|
310
|
+
interface DataLoaderProps<T> {
|
|
311
|
+
url: string;
|
|
312
|
+
children: (data: T, isLoading: boolean, error: Error | null) => React.ReactNode;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export const DataLoader = <T,>({ url, children }: DataLoaderProps<T>) => {
|
|
316
|
+
const { data, isLoading, error } = useFetch<T>(url);
|
|
317
|
+
return <>{children(data, isLoading, error)}</>;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// Usage
|
|
321
|
+
<DataLoader url="/api/users">
|
|
322
|
+
{(users, loading, error) => {
|
|
323
|
+
if (loading) return <Spinner />;
|
|
324
|
+
if (error) return <Error message={error.message} />;
|
|
325
|
+
return <UserList users={users} />;
|
|
326
|
+
}}
|
|
327
|
+
</DataLoader>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Pattern: Custom Hooks (Logic Extraction)
|
|
331
|
+
|
|
332
|
+
Extract reusable logic from components.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
// useDebounce.ts
|
|
336
|
+
export const useDebounce = <T,>(value: T, delay: number): T => {
|
|
337
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
338
|
+
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
|
341
|
+
return () => clearTimeout(timer);
|
|
342
|
+
}, [value, delay]);
|
|
343
|
+
|
|
344
|
+
return debouncedValue;
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// Usage in component
|
|
348
|
+
const SearchInput = () => {
|
|
349
|
+
const [query, setQuery] = useState('');
|
|
350
|
+
const debouncedQuery = useDebounce(query, 300);
|
|
351
|
+
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
if (debouncedQuery) {
|
|
354
|
+
searchAPI(debouncedQuery);
|
|
355
|
+
}
|
|
356
|
+
}, [debouncedQuery]);
|
|
357
|
+
|
|
358
|
+
return <input value={query} onChange={e => setQuery(e.target.value)} />;
|
|
359
|
+
};
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## 🎨 Styling Strategy
|
|
365
|
+
|
|
366
|
+
**Approach:** {{STYLING_APPROACH}}
|
|
367
|
+
|
|
368
|
+
{{STYLING_DESCRIPTION}}
|
|
369
|
+
|
|
370
|
+
### Component Styling Example
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
// Using {{STYLING_APPROACH}}
|
|
374
|
+
{{STYLING_EXAMPLE}}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 🧪 Component Testing
|
|
380
|
+
|
|
381
|
+
### What to Test
|
|
382
|
+
|
|
383
|
+
1. **Component renders correctly** with different props
|
|
384
|
+
2. **User interactions** trigger expected behaviors
|
|
385
|
+
3. **Conditional rendering** shows/hides correctly
|
|
386
|
+
4. **Accessibility** works with keyboard and screen readers
|
|
387
|
+
|
|
388
|
+
### Testing Example
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
// Button.test.tsx
|
|
392
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
393
|
+
import { Button } from './Button';
|
|
394
|
+
|
|
395
|
+
describe('Button', () => {
|
|
396
|
+
it('renders children correctly', () => {
|
|
397
|
+
render(<Button>Click me</Button>);
|
|
398
|
+
expect(screen.getByText('Click me')).toBeInTheDocument();
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('calls onClick when clicked', () => {
|
|
402
|
+
const handleClick = jest.fn();
|
|
403
|
+
render(<Button onClick={handleClick}>Click me</Button>);
|
|
404
|
+
|
|
405
|
+
fireEvent.click(screen.getByText('Click me'));
|
|
406
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('is disabled when disabled prop is true', () => {
|
|
410
|
+
render(<Button disabled>Click me</Button>);
|
|
411
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it('applies correct variant class', () => {
|
|
415
|
+
render(<Button variant="danger">Delete</Button>);
|
|
416
|
+
expect(screen.getByRole('button')).toHaveClass('btn-danger');
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## 📦 Component Library
|
|
424
|
+
|
|
425
|
+
{{#IF_COMPONENT_LIBRARY}}
|
|
426
|
+
**Using:** {{COMPONENT_LIBRARY}}
|
|
427
|
+
|
|
428
|
+
### When to Use Library Components
|
|
429
|
+
|
|
430
|
+
- ✅ Complex components (datepickers, modals, dropdowns)
|
|
431
|
+
- ✅ Accessibility-critical components
|
|
432
|
+
- ✅ Time-saving for standard UI patterns
|
|
433
|
+
|
|
434
|
+
### When to Build Custom
|
|
435
|
+
|
|
436
|
+
- ✅ Brand-specific designs
|
|
437
|
+
- ✅ Simple components (Button, Input)
|
|
438
|
+
- ✅ Performance-critical components
|
|
439
|
+
{{/IF_COMPONENT_LIBRARY}}
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 🚀 Performance Optimization
|
|
444
|
+
|
|
445
|
+
### Code Splitting
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
// Route-level code splitting
|
|
449
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
450
|
+
const Profile = lazy(() => import('./pages/Profile'));
|
|
451
|
+
|
|
452
|
+
// Component-level (for large components)
|
|
453
|
+
const HeavyChart = lazy(() => import('./components/HeavyChart'));
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Memoization
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
// React
|
|
460
|
+
const MemoizedComponent = React.memo(ExpensiveComponent);
|
|
461
|
+
const memoizedValue = useMemo(() => computeExpensive(a, b), [a, b]);
|
|
462
|
+
const memoizedCallback = useCallback(() => doSomething(a), [a]);
|
|
463
|
+
|
|
464
|
+
// Vue
|
|
465
|
+
const computed Value = computed(() => expensiveComputation());
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Virtualization (Long Lists)
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
// React
|
|
472
|
+
import { FixedSizeList } from 'react-window';
|
|
473
|
+
|
|
474
|
+
<FixedSizeList
|
|
475
|
+
height={600}
|
|
476
|
+
itemCount={items.length}
|
|
477
|
+
itemSize={50}
|
|
478
|
+
>
|
|
479
|
+
{({ index, style }) => (
|
|
480
|
+
<div style={style}>{items[index].name}</div>
|
|
481
|
+
)}
|
|
482
|
+
</FixedSizeList>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
## ♿ Accessibility Guidelines
|
|
488
|
+
|
|
489
|
+
### Semantic HTML
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
// ❌ Bad
|
|
493
|
+
<div onClick={handleClick}>Submit</div>
|
|
494
|
+
|
|
495
|
+
// ✅ Good
|
|
496
|
+
<button onClick={handleClick}>Submit</button>
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### ARIA Attributes
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
<button
|
|
503
|
+
aria-label="Close dialog"
|
|
504
|
+
aria-pressed={isPressed}
|
|
505
|
+
aria-expanded={isExpanded}
|
|
506
|
+
>
|
|
507
|
+
<CloseIcon />
|
|
508
|
+
</button>
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Keyboard Navigation
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
515
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
516
|
+
handleAction();
|
|
517
|
+
}
|
|
518
|
+
if (e.key === 'Escape') {
|
|
519
|
+
handleClose();
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## 📚 Component Documentation
|
|
527
|
+
|
|
528
|
+
### JSDoc Comments
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
/**
|
|
532
|
+
* Primary button component for user actions
|
|
533
|
+
*
|
|
534
|
+
* @component
|
|
535
|
+
* @example
|
|
536
|
+
* <Button variant="primary" onClick={handleSubmit}>
|
|
537
|
+
* Submit Form
|
|
538
|
+
* </Button>
|
|
539
|
+
*/
|
|
540
|
+
export const Button: React.FC<ButtonProps> = ({ ... }) => { ... };
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### README per Feature
|
|
544
|
+
|
|
545
|
+
Each feature directory should have a README explaining:
|
|
546
|
+
- Purpose of the feature
|
|
547
|
+
- Key components
|
|
548
|
+
- Data flow
|
|
549
|
+
- API dependencies
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## 🔗 Related Documents
|
|
554
|
+
|
|
555
|
+
- [AI Instructions](../ai-instructions.md) - Development guidelines
|
|
556
|
+
- [State Management](state-management.md) - State patterns
|
|
557
|
+
- [Styling Guide](styling.md) - Styling conventions
|
|
558
|
+
- [Testing Strategy](testing.md) - Testing approach
|
|
559
|
+
- [Performance](performance.md) - Optimization techniques
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
564
|
+
|
|
565
|
+
**Pattern:** {{COMPONENT_PATTERN}}
|
|
566
|
+
|
|
567
|
+
**Framework:** {{UI_FRAMEWORK}} {{UI_FRAMEWORK_VERSION}}
|