maestro-bundle 1.3.1 → 1.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/package.json +1 -1
- package/templates/bundle-ai-agents/skills/agent-orchestration/SKILL.md +107 -41
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/graph-patterns.md +50 -0
- package/templates/bundle-ai-agents/skills/agent-orchestration/references/routing-strategies.md +47 -0
- package/templates/bundle-ai-agents/skills/api-design/SKILL.md +125 -16
- package/templates/bundle-ai-agents/skills/api-design/references/pydantic-patterns.md +72 -0
- package/templates/bundle-ai-agents/skills/api-design/references/rest-conventions.md +51 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/SKILL.md +113 -21
- package/templates/bundle-ai-agents/skills/clean-architecture/references/dependency-injection.md +60 -0
- package/templates/bundle-ai-agents/skills/clean-architecture/references/layer-rules.md +56 -0
- package/templates/bundle-ai-agents/skills/context-engineering/SKILL.md +104 -36
- package/templates/bundle-ai-agents/skills/context-engineering/references/compression-techniques.md +76 -0
- package/templates/bundle-ai-agents/skills/context-engineering/references/context-budget-calculator.md +45 -0
- package/templates/bundle-ai-agents/skills/database-modeling/SKILL.md +146 -19
- package/templates/bundle-ai-agents/skills/database-modeling/references/index-strategies.md +48 -0
- package/templates/bundle-ai-agents/skills/database-modeling/references/naming-conventions.md +27 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/SKILL.md +124 -15
- package/templates/bundle-ai-agents/skills/docker-containerization/references/compose-patterns.md +97 -0
- package/templates/bundle-ai-agents/skills/docker-containerization/references/dockerfile-checklist.md +37 -0
- package/templates/bundle-ai-agents/skills/eval-testing/SKILL.md +113 -25
- package/templates/bundle-ai-agents/skills/eval-testing/references/eval-types.md +52 -0
- package/templates/bundle-ai-agents/skills/eval-testing/references/golden-dataset-template.md +59 -0
- package/templates/bundle-ai-agents/skills/memory-management/SKILL.md +112 -28
- package/templates/bundle-ai-agents/skills/memory-management/references/memory-tiers.md +41 -0
- package/templates/bundle-ai-agents/skills/memory-management/references/namespace-conventions.md +41 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/SKILL.md +139 -47
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/anti-patterns.md +59 -0
- package/templates/bundle-ai-agents/skills/prompt-engineering/references/prompt-templates.md +75 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/SKILL.md +104 -27
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/chunking-strategies.md +27 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/embedding-models.md +31 -0
- package/templates/bundle-ai-agents/skills/rag-pipeline/references/rag-evaluation.md +39 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/SKILL.md +127 -18
- package/templates/bundle-ai-agents/skills/testing-strategy/references/fixture-patterns.md +81 -0
- package/templates/bundle-ai-agents/skills/testing-strategy/references/naming-conventions.md +69 -0
- package/templates/bundle-base/skills/branch-strategy/SKILL.md +134 -21
- package/templates/bundle-base/skills/branch-strategy/references/branch-rules.md +40 -0
- package/templates/bundle-base/skills/code-review/SKILL.md +123 -38
- package/templates/bundle-base/skills/code-review/references/review-checklist.md +45 -0
- package/templates/bundle-base/skills/commit-pattern/SKILL.md +98 -39
- package/templates/bundle-base/skills/commit-pattern/references/conventional-commits.md +40 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/SKILL.md +110 -19
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandas-cheatsheet.md +63 -0
- package/templates/bundle-data-pipeline/skills/data-preprocessing/references/pandera-schemas.md +44 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/SKILL.md +132 -16
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/compose-patterns.md +82 -0
- package/templates/bundle-data-pipeline/skills/docker-containerization/references/dockerfile-best-practices.md +57 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/SKILL.md +143 -45
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/encoding-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/feature-engineering/references/scaling-guide.md +38 -0
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/SKILL.md +156 -37
- package/templates/bundle-data-pipeline/skills/mlops-pipeline/references/mlflow-commands.md +69 -0
- package/templates/bundle-data-pipeline/skills/model-training/SKILL.md +152 -33
- package/templates/bundle-data-pipeline/skills/model-training/references/evaluation-metrics.md +52 -0
- package/templates/bundle-data-pipeline/skills/model-training/references/model-selection-guide.md +41 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/SKILL.md +127 -39
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/chunking-strategies.md +51 -0
- package/templates/bundle-data-pipeline/skills/rag-pipeline/references/embedding-models.md +49 -0
- package/templates/bundle-frontend-spa/skills/authentication/SKILL.md +196 -13
- package/templates/bundle-frontend-spa/skills/authentication/references/jwt-security.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/SKILL.md +191 -41
- package/templates/bundle-frontend-spa/skills/component-design/references/accessibility-checklist.md +41 -0
- package/templates/bundle-frontend-spa/skills/component-design/references/tailwind-patterns.md +65 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/SKILL.md +241 -79
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/playwright-selectors.md +66 -0
- package/templates/bundle-frontend-spa/skills/e2e-testing/references/test-patterns.md +82 -0
- package/templates/bundle-frontend-spa/skills/integration-api/SKILL.md +221 -31
- package/templates/bundle-frontend-spa/skills/integration-api/references/api-patterns.md +81 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/SKILL.md +195 -70
- package/templates/bundle-frontend-spa/skills/react-patterns/references/component-checklist.md +22 -0
- package/templates/bundle-frontend-spa/skills/react-patterns/references/hook-patterns.md +63 -0
- package/templates/bundle-frontend-spa/skills/responsive-layout/SKILL.md +162 -22
- package/templates/bundle-frontend-spa/skills/responsive-layout/references/breakpoint-guide.md +63 -0
- package/templates/bundle-frontend-spa/skills/state-management/SKILL.md +158 -30
- package/templates/bundle-frontend-spa/skills/state-management/references/react-query-config.md +64 -0
- package/templates/bundle-frontend-spa/skills/state-management/references/state-patterns.md +78 -0
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/SKILL.md +135 -45
- package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/references/gitlab-ci-templates.md +93 -0
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-microservices/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-microservices/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/SKILL.md +63 -21
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-microservices.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/SKILL.md +125 -91
- package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/references/docker-k8s-commands.md +68 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/SKILL.md +72 -20
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/cross-service-entities.md +36 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/SKILL.md +80 -8
- package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/references/gateway-config.md +43 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/SKILL.md +115 -22
- package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/references/kafka-events.md +39 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/SKILL.md +92 -23
- package/templates/bundle-jhipster-microservices/skills/jhipster-registry/references/consul-config.md +61 -0
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/SKILL.md +81 -18
- package/templates/bundle-jhipster-microservices/skills/jhipster-service/references/service-patterns.md +40 -0
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-microservices/skills/testing-strategy/references/test-naming.md +55 -0
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/SKILL.md +87 -21
- package/templates/bundle-jhipster-monorepo/skills/clean-architecture/references/layer-rules.md +78 -0
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/SKILL.md +94 -25
- package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/references/ddd-patterns.md +48 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/SKILL.md +99 -52
- package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/references/angular-structure.md +59 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/SKILL.md +89 -36
- package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/references/jdl-types.md +56 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/SKILL.md +123 -23
- package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/references/liquibase-operations.md +95 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/SKILL.md +106 -19
- package/templates/bundle-jhipster-monorepo/skills/jhipster-security/references/security-checklist.md +47 -0
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/SKILL.md +84 -16
- package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/references/spring-layers.md +41 -0
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/SKILL.md +101 -20
- package/templates/bundle-jhipster-monorepo/skills/testing-strategy/references/test-naming.md +55 -0
|
@@ -1,81 +1,140 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: react-patterns
|
|
3
|
-
description:
|
|
3
|
+
description: Implement React patterns with TypeScript including custom hooks, composition, container/presenter, error boundaries, and forms with validation. Use when you need to create React components, structure features, build forms, or solve frontend architecture problems.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Maestro
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# React Patterns
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Apply proven React + TypeScript patterns for scalable, maintainable frontend code.
|
|
9
11
|
|
|
12
|
+
## When to Use
|
|
13
|
+
- User needs to create a custom hook for data fetching or shared logic
|
|
14
|
+
- User wants to structure a feature using container/presenter pattern
|
|
15
|
+
- User needs to build a form with validation (React Hook Form + Zod)
|
|
16
|
+
- User wants to add error boundaries to catch rendering errors
|
|
17
|
+
- User needs to compose components instead of using deep prop drilling
|
|
18
|
+
|
|
19
|
+
## Available Operations
|
|
20
|
+
1. Create custom hooks for data fetching with React Query
|
|
21
|
+
2. Build components using composition pattern (slots, children)
|
|
22
|
+
3. Implement container/presenter separation
|
|
23
|
+
4. Add error boundaries with recovery
|
|
24
|
+
5. Build validated forms with React Hook Form + Zod
|
|
25
|
+
|
|
26
|
+
## Multi-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Set Up Project Dependencies
|
|
29
|
+
```bash
|
|
30
|
+
npm install @tanstack/react-query react-hook-form @hookform/resolvers zod react-error-boundary
|
|
31
|
+
npm install -D @types/react @types/react-dom typescript
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Step 2: Create Custom Hooks for Data Fetching
|
|
10
35
|
```tsx
|
|
11
|
-
// hooks/
|
|
12
|
-
|
|
36
|
+
// src/hooks/useItems.ts
|
|
37
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
38
|
+
import { itemApi } from '../services/itemApi';
|
|
39
|
+
import { toast } from 'sonner';
|
|
40
|
+
|
|
41
|
+
export function useItems(filters?: ItemFilters) {
|
|
13
42
|
return useQuery({
|
|
14
|
-
queryKey: ['
|
|
15
|
-
queryFn: () =>
|
|
43
|
+
queryKey: ['items', filters],
|
|
44
|
+
queryFn: () => itemApi.list(filters),
|
|
16
45
|
staleTime: 30_000,
|
|
17
46
|
});
|
|
18
47
|
}
|
|
19
48
|
|
|
20
|
-
export function
|
|
49
|
+
export function useItem(id: string) {
|
|
50
|
+
return useQuery({
|
|
51
|
+
queryKey: ['items', id],
|
|
52
|
+
queryFn: () => itemApi.get(id),
|
|
53
|
+
enabled: !!id,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function useCreateItem() {
|
|
21
58
|
const queryClient = useQueryClient();
|
|
22
59
|
return useMutation({
|
|
23
|
-
mutationFn:
|
|
60
|
+
mutationFn: itemApi.create,
|
|
24
61
|
onSuccess: () => {
|
|
25
|
-
queryClient.invalidateQueries({ queryKey: ['
|
|
26
|
-
toast.success('
|
|
62
|
+
queryClient.invalidateQueries({ queryKey: ['items'] });
|
|
63
|
+
toast.success('Item created');
|
|
27
64
|
},
|
|
28
65
|
onError: (err) => toast.error(err.message),
|
|
29
66
|
});
|
|
30
67
|
}
|
|
31
68
|
```
|
|
32
69
|
|
|
33
|
-
|
|
34
|
-
|
|
70
|
+
### Step 3: Build Components with Composition
|
|
35
71
|
```tsx
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<Card.Content>
|
|
45
|
-
<AgentTeamList agents={demand.assignedAgents} />
|
|
46
|
-
</Card.Content>
|
|
47
|
-
<Card.Footer>
|
|
48
|
-
<TaskProgress tasks={demand.tasks} />
|
|
49
|
-
</Card.Footer>
|
|
50
|
-
</Card>
|
|
51
|
-
);
|
|
72
|
+
// src/components/Card.tsx
|
|
73
|
+
interface CardProps {
|
|
74
|
+
children: React.ReactNode;
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function Card({ children, className }: CardProps) {
|
|
79
|
+
return <div className={cn('rounded-lg border bg-white shadow-sm', className)}>{children}</div>;
|
|
52
80
|
}
|
|
53
|
-
```
|
|
54
81
|
|
|
55
|
-
|
|
82
|
+
Card.Header = function CardHeader({ children }: { children: React.ReactNode }) {
|
|
83
|
+
return <div className="flex items-center justify-between p-4 border-b">{children}</div>;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Card.Content = function CardContent({ children }: { children: React.ReactNode }) {
|
|
87
|
+
return <div className="p-4">{children}</div>;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
Card.Footer = function CardFooter({ children }: { children: React.ReactNode }) {
|
|
91
|
+
return <div className="p-4 border-t bg-gray-50">{children}</div>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Usage:
|
|
95
|
+
<Card>
|
|
96
|
+
<Card.Header>
|
|
97
|
+
<h3>{item.title}</h3>
|
|
98
|
+
<StatusBadge status={item.status} />
|
|
99
|
+
</Card.Header>
|
|
100
|
+
<Card.Content>
|
|
101
|
+
<p>{item.description}</p>
|
|
102
|
+
</Card.Content>
|
|
103
|
+
<Card.Footer>
|
|
104
|
+
<ProgressBar value={item.progress} />
|
|
105
|
+
</Card.Footer>
|
|
106
|
+
</Card>
|
|
107
|
+
```
|
|
56
108
|
|
|
109
|
+
### Step 4: Implement Container/Presenter Pattern
|
|
57
110
|
```tsx
|
|
58
|
-
// Container
|
|
59
|
-
function
|
|
60
|
-
const { data, isLoading, error } =
|
|
111
|
+
// Container: owns data fetching and state
|
|
112
|
+
function ItemListContainer() {
|
|
113
|
+
const { data, isLoading, error } = useItems();
|
|
61
114
|
const [selected, setSelected] = useState<string | null>(null);
|
|
62
115
|
|
|
63
116
|
if (isLoading) return <Skeleton />;
|
|
64
117
|
if (error) return <ErrorState message={error.message} />;
|
|
65
118
|
|
|
66
|
-
return <
|
|
119
|
+
return <ItemList items={data!} selected={selected} onSelect={setSelected} />;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Presenter: pure rendering, easy to test
|
|
123
|
+
interface ItemListProps {
|
|
124
|
+
items: Item[];
|
|
125
|
+
selected: string | null;
|
|
126
|
+
onSelect: (id: string) => void;
|
|
67
127
|
}
|
|
68
128
|
|
|
69
|
-
|
|
70
|
-
function DemandList({ demands, selected, onSelect }: DemandListProps) {
|
|
129
|
+
function ItemList({ items, selected, onSelect }: ItemListProps) {
|
|
71
130
|
return (
|
|
72
131
|
<div className="grid gap-4">
|
|
73
|
-
{
|
|
74
|
-
<
|
|
75
|
-
key={
|
|
76
|
-
|
|
77
|
-
isSelected={
|
|
78
|
-
onClick={() => onSelect(
|
|
132
|
+
{items.map((item) => (
|
|
133
|
+
<ItemCard
|
|
134
|
+
key={item.id}
|
|
135
|
+
item={item}
|
|
136
|
+
isSelected={item.id === selected}
|
|
137
|
+
onClick={() => onSelect(item.id)}
|
|
79
138
|
/>
|
|
80
139
|
))}
|
|
81
140
|
</div>
|
|
@@ -83,48 +142,114 @@ function DemandList({ demands, selected, onSelect }: DemandListProps) {
|
|
|
83
142
|
}
|
|
84
143
|
```
|
|
85
144
|
|
|
86
|
-
|
|
87
|
-
|
|
145
|
+
### Step 5: Add Error Boundaries
|
|
88
146
|
```tsx
|
|
89
|
-
|
|
147
|
+
// src/components/AppErrorBoundary.tsx
|
|
148
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
149
|
+
|
|
150
|
+
function ErrorFallback({ error, resetErrorBoundary }: { error: Error; resetErrorBoundary: () => void }) {
|
|
90
151
|
return (
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
)}
|
|
99
|
-
>
|
|
100
|
-
{children}
|
|
101
|
-
</ErrorBoundary>
|
|
152
|
+
<div className="p-8 text-center">
|
|
153
|
+
<h2 className="text-xl font-bold text-red-600">Something went wrong</h2>
|
|
154
|
+
<p className="mt-2 text-gray-600">{error.message}</p>
|
|
155
|
+
<button onClick={resetErrorBoundary} className="mt-4 px-4 py-2 bg-blue-600 text-white rounded">
|
|
156
|
+
Try again
|
|
157
|
+
</button>
|
|
158
|
+
</div>
|
|
102
159
|
);
|
|
103
160
|
}
|
|
104
|
-
```
|
|
105
161
|
|
|
106
|
-
|
|
162
|
+
export function AppErrorBoundary({ children }: { children: React.ReactNode }) {
|
|
163
|
+
return <ErrorBoundary FallbackComponent={ErrorFallback}>{children}</ErrorBoundary>;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
107
166
|
|
|
167
|
+
### Step 6: Build Validated Forms
|
|
108
168
|
```tsx
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
169
|
+
// src/features/items/CreateItemForm.tsx
|
|
170
|
+
import { useForm } from 'react-hook-form';
|
|
171
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
172
|
+
import { z } from 'zod';
|
|
173
|
+
|
|
174
|
+
const itemSchema = z.object({
|
|
175
|
+
title: z.string().min(3, 'Title must be at least 3 characters'),
|
|
176
|
+
description: z.string().min(10, 'Description must be at least 10 characters'),
|
|
112
177
|
priority: z.enum(['low', 'medium', 'high']),
|
|
113
178
|
});
|
|
114
179
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
180
|
+
type ItemFormData = z.infer<typeof itemSchema>;
|
|
181
|
+
|
|
182
|
+
export function CreateItemForm() {
|
|
183
|
+
const { register, handleSubmit, formState: { errors } } = useForm<ItemFormData>({
|
|
184
|
+
resolver: zodResolver(itemSchema),
|
|
118
185
|
});
|
|
119
|
-
const
|
|
186
|
+
const createItem = useCreateItem();
|
|
120
187
|
|
|
121
188
|
return (
|
|
122
|
-
<form onSubmit={handleSubmit(data =>
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
189
|
+
<form onSubmit={handleSubmit((data) => createItem.mutate(data))}>
|
|
190
|
+
<div>
|
|
191
|
+
<label htmlFor="title">Title</label>
|
|
192
|
+
<input id="title" {...register('title')} className="border rounded p-2 w-full" />
|
|
193
|
+
{errors.title && <p className="text-red-500 text-sm">{errors.title.message}</p>}
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<div>
|
|
197
|
+
<label htmlFor="description">Description</label>
|
|
198
|
+
<textarea id="description" {...register('description')} className="border rounded p-2 w-full" />
|
|
199
|
+
{errors.description && <p className="text-red-500 text-sm">{errors.description.message}</p>}
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div>
|
|
203
|
+
<label htmlFor="priority">Priority</label>
|
|
204
|
+
<select id="priority" {...register('priority')} className="border rounded p-2 w-full">
|
|
205
|
+
<option value="low">Low</option>
|
|
206
|
+
<option value="medium">Medium</option>
|
|
207
|
+
<option value="high">High</option>
|
|
208
|
+
</select>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<button type="submit" disabled={createItem.isPending} className="mt-4 px-4 py-2 bg-blue-600 text-white rounded">
|
|
212
|
+
{createItem.isPending ? 'Creating...' : 'Create'}
|
|
213
|
+
</button>
|
|
127
214
|
</form>
|
|
128
215
|
);
|
|
129
216
|
}
|
|
130
217
|
```
|
|
218
|
+
|
|
219
|
+
### Step 7: Verify the Pattern Works
|
|
220
|
+
```bash
|
|
221
|
+
npm run dev
|
|
222
|
+
# Open http://localhost:5173 and test the feature
|
|
223
|
+
|
|
224
|
+
npm run type-check
|
|
225
|
+
# or: npx tsc --noEmit
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Resources
|
|
229
|
+
- `references/hook-patterns.md` - Custom hook patterns and anti-patterns
|
|
230
|
+
- `references/component-checklist.md` - Quality checklist for React components
|
|
231
|
+
|
|
232
|
+
## Examples
|
|
233
|
+
### Example 1: Create a Data Fetching Hook
|
|
234
|
+
User asks: "Create a hook to fetch and cache user profiles"
|
|
235
|
+
Response approach:
|
|
236
|
+
1. Create `useUser(id)` and `useUsers(filters)` hooks using React Query
|
|
237
|
+
2. Add `useCreateUser()` mutation with cache invalidation
|
|
238
|
+
3. Add toast notifications for success/error states
|
|
239
|
+
4. Show usage in a container component
|
|
240
|
+
|
|
241
|
+
### Example 2: Build a Feature Module
|
|
242
|
+
User asks: "Create the orders feature with list, detail, and create form"
|
|
243
|
+
Response approach:
|
|
244
|
+
1. Create `useOrders()` and `useCreateOrder()` hooks
|
|
245
|
+
2. Build `OrderList` presenter and `OrderListContainer`
|
|
246
|
+
3. Build `CreateOrderForm` with Zod validation
|
|
247
|
+
4. Wrap in `ErrorBoundary`
|
|
248
|
+
5. Add route entries and test with `npm run dev`
|
|
249
|
+
|
|
250
|
+
## Notes
|
|
251
|
+
- Prefer composition (children, render props) over configuration (boolean props)
|
|
252
|
+
- Never duplicate API data in Zustand -- use React Query for server state
|
|
253
|
+
- Keep presenters pure: no hooks, no side effects, just props and JSX
|
|
254
|
+
- Always type props with TypeScript interfaces, not `any`
|
|
255
|
+
- Use `enabled: !!id` in useQuery to prevent fetching with empty IDs
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Component Quality Checklist
|
|
2
|
+
|
|
3
|
+
## Before Shipping a Component
|
|
4
|
+
- [ ] Props are typed with a TypeScript interface (not `any`)
|
|
5
|
+
- [ ] Component has a single, clear responsibility
|
|
6
|
+
- [ ] Loading, error, and empty states are handled
|
|
7
|
+
- [ ] Accessible: has aria-labels, keyboard navigation where needed
|
|
8
|
+
- [ ] No business logic in presenter components
|
|
9
|
+
- [ ] Uses composition (children/slots) over boolean prop flags
|
|
10
|
+
- [ ] All event handlers are properly typed
|
|
11
|
+
- [ ] No inline styles -- uses Tailwind classes or CSS modules
|
|
12
|
+
|
|
13
|
+
## Performance
|
|
14
|
+
- [ ] Lists use unique `key` props (not array index)
|
|
15
|
+
- [ ] Heavy computations wrapped in `useMemo`
|
|
16
|
+
- [ ] Callbacks passed to children wrapped in `useCallback` when needed
|
|
17
|
+
- [ ] Large components are code-split with `React.lazy()`
|
|
18
|
+
|
|
19
|
+
## Testing
|
|
20
|
+
- [ ] Presenter components have unit tests with React Testing Library
|
|
21
|
+
- [ ] Custom hooks have tests using `renderHook`
|
|
22
|
+
- [ ] Edge cases tested: empty data, error states, loading states
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Custom Hook Patterns
|
|
2
|
+
|
|
3
|
+
## Data Fetching Hook (React Query)
|
|
4
|
+
```tsx
|
|
5
|
+
export function useItems(filters?: Filters) {
|
|
6
|
+
return useQuery({
|
|
7
|
+
queryKey: ['items', filters],
|
|
8
|
+
queryFn: () => api.list(filters),
|
|
9
|
+
staleTime: 30_000, // cache for 30s
|
|
10
|
+
retry: 2, // retry failed requests twice
|
|
11
|
+
enabled: filters !== undefined, // conditional fetching
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Mutation Hook with Cache Invalidation
|
|
17
|
+
```tsx
|
|
18
|
+
export function useCreateItem() {
|
|
19
|
+
const qc = useQueryClient();
|
|
20
|
+
return useMutation({
|
|
21
|
+
mutationFn: api.create,
|
|
22
|
+
onSuccess: () => {
|
|
23
|
+
qc.invalidateQueries({ queryKey: ['items'] });
|
|
24
|
+
toast.success('Created');
|
|
25
|
+
},
|
|
26
|
+
onError: (err) => toast.error(err.message),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Debounced Value Hook
|
|
32
|
+
```tsx
|
|
33
|
+
export function useDebounce<T>(value: T, delay: number): T {
|
|
34
|
+
const [debounced, setDebounced] = useState(value);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const timer = setTimeout(() => setDebounced(value), delay);
|
|
37
|
+
return () => clearTimeout(timer);
|
|
38
|
+
}, [value, delay]);
|
|
39
|
+
return debounced;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Local Storage Hook
|
|
44
|
+
```tsx
|
|
45
|
+
export function useLocalStorage<T>(key: string, initial: T) {
|
|
46
|
+
const [value, setValue] = useState<T>(() => {
|
|
47
|
+
const stored = localStorage.getItem(key);
|
|
48
|
+
return stored ? JSON.parse(stored) : initial;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
53
|
+
}, [key, value]);
|
|
54
|
+
|
|
55
|
+
return [value, setValue] as const;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Anti-Patterns to Avoid
|
|
60
|
+
1. Do NOT call hooks conditionally (`if (x) useEffect(...)`)
|
|
61
|
+
2. Do NOT duplicate server state in useState -- use React Query
|
|
62
|
+
3. Do NOT create hooks that do too many things -- split them
|
|
63
|
+
4. Do NOT forget cleanup in useEffect return functions
|
|
@@ -1,19 +1,55 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: responsive-layout
|
|
3
|
-
description:
|
|
3
|
+
description: Create responsive layouts with Tailwind CSS including sidebar navigation, dashboard grids, and mobile-first design. Use when you need to build page layouts, dashboards, responsive grids, or navigation structures.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Maestro
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Responsive Layout
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Build mobile-first responsive layouts using Tailwind CSS with sidebar navigation, dashboard grids, and adaptive content areas.
|
|
9
11
|
|
|
12
|
+
## When to Use
|
|
13
|
+
- User needs to create a page layout with sidebar and header
|
|
14
|
+
- User wants to build a responsive dashboard with metric cards
|
|
15
|
+
- User needs a mobile-first grid that adapts to screen sizes
|
|
16
|
+
- User wants to add responsive navigation (sidebar + mobile menu)
|
|
17
|
+
- User needs to structure a page with proper spacing and overflow handling
|
|
18
|
+
|
|
19
|
+
## Available Operations
|
|
20
|
+
1. Create a full app layout (sidebar + header + main content)
|
|
21
|
+
2. Build responsive dashboard grids with metric cards
|
|
22
|
+
3. Implement collapsible sidebar with mobile drawer
|
|
23
|
+
4. Set up responsive content grids
|
|
24
|
+
5. Add proper scroll areas and overflow handling
|
|
25
|
+
|
|
26
|
+
## Multi-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Install Dependencies
|
|
29
|
+
```bash
|
|
30
|
+
npm install clsx tailwind-merge lucide-react
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Verify Tailwind is configured:
|
|
34
|
+
```bash
|
|
35
|
+
npx tailwindcss --help
|
|
36
|
+
# If not installed: npm install -D tailwindcss postcss autoprefixer && npx tailwindcss init -p
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Step 2: Create the App Shell Layout
|
|
10
40
|
```tsx
|
|
11
|
-
|
|
12
|
-
|
|
41
|
+
// src/layouts/AppLayout.tsx
|
|
42
|
+
import { useAppStore } from '@/stores/useAppStore';
|
|
43
|
+
|
|
44
|
+
export function AppLayout({ children }: { children: React.ReactNode }) {
|
|
45
|
+
const sidebarOpen = useAppStore((s) => s.sidebarOpen);
|
|
13
46
|
|
|
14
47
|
return (
|
|
15
48
|
<div className="flex h-screen bg-gray-50">
|
|
49
|
+
{/* Sidebar */}
|
|
16
50
|
<Sidebar open={sidebarOpen} />
|
|
51
|
+
|
|
52
|
+
{/* Main area */}
|
|
17
53
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
18
54
|
<Header />
|
|
19
55
|
<main className="flex-1 overflow-y-auto p-4 md:p-6 lg:p-8">
|
|
@@ -25,41 +61,145 @@ function AppLayout({ children }: { children: React.ReactNode }) {
|
|
|
25
61
|
}
|
|
26
62
|
```
|
|
27
63
|
|
|
28
|
-
|
|
64
|
+
### Step 3: Build the Sidebar
|
|
65
|
+
```tsx
|
|
66
|
+
// src/components/Sidebar.tsx
|
|
67
|
+
import { NavLink } from 'react-router-dom';
|
|
68
|
+
import { Home, List, Users, Settings, X } from 'lucide-react';
|
|
69
|
+
import { useAppStore } from '@/stores/useAppStore';
|
|
70
|
+
|
|
71
|
+
const navItems = [
|
|
72
|
+
{ to: '/dashboard', label: 'Dashboard', icon: Home },
|
|
73
|
+
{ to: '/items', label: 'Items', icon: List },
|
|
74
|
+
{ to: '/team', label: 'Team', icon: Users },
|
|
75
|
+
{ to: '/settings', label: 'Settings', icon: Settings },
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
export function Sidebar({ open }: { open: boolean }) {
|
|
79
|
+
const toggleSidebar = useAppStore((s) => s.toggleSidebar);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
{/* Mobile overlay */}
|
|
84
|
+
{open && (
|
|
85
|
+
<div className="fixed inset-0 bg-black/50 z-40 lg:hidden" onClick={toggleSidebar} />
|
|
86
|
+
)}
|
|
87
|
+
|
|
88
|
+
{/* Sidebar */}
|
|
89
|
+
<aside
|
|
90
|
+
className={cn(
|
|
91
|
+
'fixed lg:static inset-y-0 left-0 z-50 w-64 bg-white border-r transform transition-transform lg:translate-x-0',
|
|
92
|
+
open ? 'translate-x-0' : '-translate-x-full'
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
<div className="flex items-center justify-between p-4 border-b">
|
|
96
|
+
<h1 className="text-xl font-bold">App Name</h1>
|
|
97
|
+
<button onClick={toggleSidebar} className="lg:hidden">
|
|
98
|
+
<X className="w-5 h-5" />
|
|
99
|
+
</button>
|
|
100
|
+
</div>
|
|
29
101
|
|
|
102
|
+
<nav className="p-4 space-y-1">
|
|
103
|
+
{navItems.map((item) => (
|
|
104
|
+
<NavLink
|
|
105
|
+
key={item.to}
|
|
106
|
+
to={item.to}
|
|
107
|
+
className={({ isActive }) =>
|
|
108
|
+
cn('flex items-center gap-3 px-3 py-2 rounded-lg text-sm',
|
|
109
|
+
isActive ? 'bg-blue-50 text-blue-700 font-medium' : 'text-gray-600 hover:bg-gray-100'
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
>
|
|
113
|
+
<item.icon className="w-5 h-5" />
|
|
114
|
+
{item.label}
|
|
115
|
+
</NavLink>
|
|
116
|
+
))}
|
|
117
|
+
</nav>
|
|
118
|
+
</aside>
|
|
119
|
+
</>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Step 4: Build a Dashboard Grid
|
|
30
125
|
```tsx
|
|
31
|
-
|
|
126
|
+
// src/pages/Dashboard.tsx
|
|
127
|
+
import { Activity, Users, Shield, CheckCircle } from 'lucide-react';
|
|
128
|
+
|
|
129
|
+
export function Dashboard() {
|
|
32
130
|
return (
|
|
33
131
|
<div className="space-y-6">
|
|
34
|
-
{/*
|
|
132
|
+
{/* Metric cards: 1 col mobile, 2 cols tablet, 4 cols desktop */}
|
|
35
133
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
36
|
-
<MetricCard title="
|
|
37
|
-
<MetricCard title="
|
|
38
|
-
<MetricCard title="Compliance
|
|
39
|
-
<MetricCard title="Tasks
|
|
134
|
+
<MetricCard title="Active Items" value={12} icon={<Activity className="w-5 h-5" />} />
|
|
135
|
+
<MetricCard title="Team Members" value={8} icon={<Users className="w-5 h-5" />} />
|
|
136
|
+
<MetricCard title="Compliance" value="94%" icon={<Shield className="w-5 h-5" />} />
|
|
137
|
+
<MetricCard title="Tasks Today" value={47} icon={<CheckCircle className="w-5 h-5" />} />
|
|
40
138
|
</div>
|
|
41
139
|
|
|
42
|
-
{/*
|
|
140
|
+
{/* Two-column layout: 2/3 + 1/3 on desktop, stacked on mobile */}
|
|
43
141
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
44
142
|
<div className="lg:col-span-2">
|
|
45
|
-
<
|
|
143
|
+
<ActivityFeed />
|
|
46
144
|
</div>
|
|
47
145
|
<div>
|
|
48
|
-
<
|
|
146
|
+
<RecentItemsList />
|
|
49
147
|
</div>
|
|
50
148
|
</div>
|
|
51
149
|
</div>
|
|
52
150
|
);
|
|
53
151
|
}
|
|
152
|
+
|
|
153
|
+
function MetricCard({ title, value, icon }: { title: string; value: string | number; icon: React.ReactNode }) {
|
|
154
|
+
return (
|
|
155
|
+
<div className="bg-white rounded-lg border p-4">
|
|
156
|
+
<div className="flex items-center justify-between">
|
|
157
|
+
<span className="text-sm text-gray-600">{title}</span>
|
|
158
|
+
<span className="text-gray-400">{icon}</span>
|
|
159
|
+
</div>
|
|
160
|
+
<p className="mt-2 text-2xl font-bold">{value}</p>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
54
164
|
```
|
|
55
165
|
|
|
56
|
-
|
|
166
|
+
### Step 5: Verify Responsive Behavior
|
|
167
|
+
```bash
|
|
168
|
+
npm run dev
|
|
169
|
+
# Open http://localhost:5173
|
|
170
|
+
|
|
171
|
+
# Test responsive breakpoints:
|
|
172
|
+
# 1. Resize browser window through breakpoints (640px, 768px, 1024px, 1280px)
|
|
173
|
+
# 2. Use browser DevTools device toolbar (Ctrl+Shift+M / Cmd+Shift+M)
|
|
174
|
+
# 3. Check sidebar collapses on mobile and shows overlay
|
|
175
|
+
# 4. Check grid columns adjust at each breakpoint
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Resources
|
|
179
|
+
- `references/breakpoint-guide.md` - Tailwind breakpoints and responsive patterns
|
|
180
|
+
|
|
181
|
+
## Examples
|
|
182
|
+
### Example 1: Create a Dashboard Layout
|
|
183
|
+
User asks: "Build a dashboard page with stats cards and an activity feed"
|
|
184
|
+
Response approach:
|
|
185
|
+
1. Create AppLayout with sidebar and header
|
|
186
|
+
2. Build MetricCard component for stats
|
|
187
|
+
3. Use responsive grid: 1->2->4 columns
|
|
188
|
+
4. Add two-column section for feed + sidebar content
|
|
189
|
+
5. Test at all breakpoints with `npm run dev`
|
|
57
190
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
191
|
+
### Example 2: Add Mobile Navigation
|
|
192
|
+
User asks: "Make the sidebar work on mobile devices"
|
|
193
|
+
Response approach:
|
|
194
|
+
1. Make sidebar fixed/absolute on mobile with transform transition
|
|
195
|
+
2. Add overlay backdrop that closes sidebar on tap
|
|
196
|
+
3. Add hamburger menu button in Header (visible only on mobile: `lg:hidden`)
|
|
197
|
+
4. Connect to Zustand toggleSidebar action
|
|
198
|
+
5. Test on mobile viewport in DevTools
|
|
64
199
|
|
|
65
|
-
|
|
200
|
+
## Notes
|
|
201
|
+
- Always design mobile-first: write base styles for mobile, then add `sm:`, `md:`, `lg:` overrides
|
|
202
|
+
- Use `overflow-hidden` on the app shell and `overflow-y-auto` on scrollable content areas
|
|
203
|
+
- Use `fixed` positioning for mobile sidebar/drawer, `static` for desktop
|
|
204
|
+
- Add `transition-transform` for smooth sidebar open/close animations
|
|
205
|
+
- Test at every Tailwind breakpoint: 640px, 768px, 1024px, 1280px
|