maestro-bundle 1.3.1 → 1.5.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/README.md +19 -6
- package/package.json +1 -1
- package/src/cli.mjs +12 -1
- package/templates/bundle-ai-agents/AGENTS.md +6 -0
- package/templates/bundle-ai-agents/PRD_TEMPLATE.md +161 -0
- 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/AGENTS.md +6 -0
- package/templates/bundle-data-pipeline/PRD_TEMPLATE.md +161 -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/AGENTS.md +6 -0
- package/templates/bundle-frontend-spa/PRD_TEMPLATE.md +161 -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/AGENTS.md +6 -0
- package/templates/bundle-jhipster-microservices/PRD_TEMPLATE.md +161 -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/AGENTS.md +6 -0
- package/templates/bundle-jhipster-monorepo/PRD_TEMPLATE.md +161 -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,25 +1,70 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: component-design
|
|
3
|
-
description:
|
|
3
|
+
description: Create reusable UI components with Tailwind CSS and Shadcn/UI following design system principles. Use when you need to create buttons, cards, modals, tables, badges, or any UI element with consistent styling and accessibility.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Maestro
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Component Design
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Build accessible, reusable UI components with Tailwind CSS, Shadcn/UI, and TypeScript.
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
## When to Use
|
|
13
|
+
- User needs to create a reusable UI component (button, card, modal, table)
|
|
14
|
+
- User wants to implement a design system with consistent variants
|
|
15
|
+
- User needs data tables with pagination and sorting
|
|
16
|
+
- User wants loading skeletons, error states, or empty states
|
|
17
|
+
- User needs accessible components with ARIA labels and keyboard navigation
|
|
14
18
|
|
|
15
|
-
##
|
|
19
|
+
## Available Operations
|
|
20
|
+
1. Create variant-based components (Button, Badge, Input)
|
|
21
|
+
2. Build compound components (Card with Header/Content/Footer)
|
|
22
|
+
3. Implement data tables with TanStack Table
|
|
23
|
+
4. Create async content wrappers (loading/error/empty states)
|
|
24
|
+
5. Add Shadcn/UI components to the project
|
|
16
25
|
|
|
26
|
+
## Multi-Step Workflow
|
|
27
|
+
|
|
28
|
+
### Step 1: Set Up Shadcn/UI (If Not Already Installed)
|
|
29
|
+
```bash
|
|
30
|
+
npx shadcn@latest init
|
|
31
|
+
npx shadcn@latest add button card table badge input dialog
|
|
32
|
+
npm install @tanstack/react-table clsx tailwind-merge
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Create a utility for merging Tailwind classes:
|
|
17
36
|
```tsx
|
|
37
|
+
// src/lib/utils.ts
|
|
38
|
+
import { clsx, type ClassValue } from 'clsx';
|
|
39
|
+
import { twMerge } from 'tailwind-merge';
|
|
40
|
+
|
|
41
|
+
export function cn(...inputs: ClassValue[]) {
|
|
42
|
+
return twMerge(clsx(inputs));
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Step 2: Create a Variant-Based Button Component
|
|
47
|
+
```tsx
|
|
48
|
+
// src/components/ui/Button.tsx
|
|
49
|
+
import { cn } from '@/lib/utils';
|
|
50
|
+
|
|
51
|
+
const variants = {
|
|
52
|
+
primary: 'bg-blue-600 text-white hover:bg-blue-700',
|
|
53
|
+
secondary: 'bg-gray-100 text-gray-700 hover:bg-gray-200',
|
|
54
|
+
danger: 'bg-red-600 text-white hover:bg-red-700',
|
|
55
|
+
ghost: 'bg-transparent hover:bg-gray-100',
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
const sizes = {
|
|
59
|
+
sm: 'px-3 py-1.5 text-sm',
|
|
60
|
+
md: 'px-4 py-2 text-base',
|
|
61
|
+
lg: 'px-6 py-3 text-lg',
|
|
62
|
+
} as const;
|
|
63
|
+
|
|
18
64
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
19
|
-
variant?:
|
|
20
|
-
size?:
|
|
65
|
+
variant?: keyof typeof variants;
|
|
66
|
+
size?: keyof typeof sizes;
|
|
21
67
|
loading?: boolean;
|
|
22
|
-
children: React.ReactNode;
|
|
23
68
|
}
|
|
24
69
|
|
|
25
70
|
export function Button({
|
|
@@ -28,36 +73,43 @@ export function Button({
|
|
|
28
73
|
loading = false,
|
|
29
74
|
children,
|
|
30
75
|
disabled,
|
|
76
|
+
className,
|
|
31
77
|
...props
|
|
32
78
|
}: ButtonProps) {
|
|
33
79
|
return (
|
|
34
80
|
<button
|
|
35
81
|
className={cn(
|
|
36
|
-
'rounded font-medium transition-colors',
|
|
82
|
+
'rounded font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
37
83
|
variants[variant],
|
|
38
84
|
sizes[size],
|
|
39
|
-
(disabled || loading) && 'opacity-50 cursor-not-allowed'
|
|
85
|
+
(disabled || loading) && 'opacity-50 cursor-not-allowed',
|
|
86
|
+
className
|
|
40
87
|
)}
|
|
41
88
|
disabled={disabled || loading}
|
|
89
|
+
aria-busy={loading}
|
|
42
90
|
{...props}
|
|
43
91
|
>
|
|
44
|
-
{loading ? <
|
|
92
|
+
{loading ? <span className="animate-spin inline-block w-4 h-4 border-2 border-current border-t-transparent rounded-full" /> : children}
|
|
45
93
|
</button>
|
|
46
94
|
);
|
|
47
95
|
}
|
|
48
96
|
```
|
|
49
97
|
|
|
50
|
-
|
|
51
|
-
|
|
98
|
+
### Step 3: Create a Status Badge
|
|
52
99
|
```tsx
|
|
100
|
+
// src/components/ui/StatusBadge.tsx
|
|
53
101
|
const statusConfig = {
|
|
54
|
-
pending: { label: '
|
|
55
|
-
in_progress: { label: '
|
|
56
|
-
completed: { label: '
|
|
57
|
-
failed: { label: '
|
|
102
|
+
pending: { label: 'Pending', className: 'bg-gray-100 text-gray-700' },
|
|
103
|
+
in_progress: { label: 'In Progress', className: 'bg-blue-100 text-blue-700' },
|
|
104
|
+
completed: { label: 'Completed', className: 'bg-green-100 text-green-700' },
|
|
105
|
+
failed: { label: 'Failed', className: 'bg-red-100 text-red-700' },
|
|
58
106
|
} as const;
|
|
59
107
|
|
|
60
|
-
|
|
108
|
+
interface StatusBadgeProps {
|
|
109
|
+
status: keyof typeof statusConfig;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function StatusBadge({ status }: StatusBadgeProps) {
|
|
61
113
|
const config = statusConfig[status];
|
|
62
114
|
return (
|
|
63
115
|
<span className={cn('px-2 py-1 rounded-full text-xs font-medium', config.className)}>
|
|
@@ -67,14 +119,16 @@ export function StatusBadge({ status }: { status: keyof typeof statusConfig }) {
|
|
|
67
119
|
}
|
|
68
120
|
```
|
|
69
121
|
|
|
70
|
-
|
|
71
|
-
|
|
122
|
+
### Step 4: Build a Data Table with Pagination
|
|
72
123
|
```tsx
|
|
124
|
+
// src/components/ui/DataTable.tsx
|
|
125
|
+
import { useReactTable, getCoreRowModel, flexRender, type ColumnDef } from '@tanstack/react-table';
|
|
126
|
+
|
|
73
127
|
interface DataTableProps<T> {
|
|
74
128
|
data: T[];
|
|
75
|
-
columns: ColumnDef<T>[];
|
|
76
|
-
pagination
|
|
77
|
-
onPageChange
|
|
129
|
+
columns: ColumnDef<T, unknown>[];
|
|
130
|
+
pagination?: { page: number; size: number; total: number };
|
|
131
|
+
onPageChange?: (page: number) => void;
|
|
78
132
|
}
|
|
79
133
|
|
|
80
134
|
export function DataTable<T>({ data, columns, pagination, onPageChange }: DataTableProps<T>) {
|
|
@@ -86,30 +140,126 @@ export function DataTable<T>({ data, columns, pagination, onPageChange }: DataTa
|
|
|
86
140
|
|
|
87
141
|
return (
|
|
88
142
|
<div>
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
143
|
+
<table className="w-full border-collapse">
|
|
144
|
+
<thead>
|
|
145
|
+
{table.getHeaderGroups().map((headerGroup) => (
|
|
146
|
+
<tr key={headerGroup.id} className="border-b bg-gray-50">
|
|
147
|
+
{headerGroup.headers.map((header) => (
|
|
148
|
+
<th key={header.id} className="px-4 py-3 text-left text-sm font-medium text-gray-600">
|
|
149
|
+
{flexRender(header.column.columnDef.header, header.getContext())}
|
|
150
|
+
</th>
|
|
151
|
+
))}
|
|
152
|
+
</tr>
|
|
153
|
+
))}
|
|
154
|
+
</thead>
|
|
155
|
+
<tbody>
|
|
156
|
+
{table.getRowModel().rows.map((row) => (
|
|
157
|
+
<tr key={row.id} className="border-b hover:bg-gray-50">
|
|
158
|
+
{row.getVisibleCells().map((cell) => (
|
|
159
|
+
<td key={cell.id} className="px-4 py-3 text-sm">
|
|
160
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
161
|
+
</td>
|
|
162
|
+
))}
|
|
163
|
+
</tr>
|
|
164
|
+
))}
|
|
165
|
+
</tbody>
|
|
166
|
+
</table>
|
|
167
|
+
|
|
168
|
+
{pagination && onPageChange && (
|
|
169
|
+
<div className="flex items-center justify-between p-4">
|
|
170
|
+
<span className="text-sm text-gray-600">
|
|
171
|
+
Page {pagination.page} of {Math.ceil(pagination.total / pagination.size)}
|
|
172
|
+
</span>
|
|
173
|
+
<div className="flex gap-2">
|
|
174
|
+
<Button size="sm" variant="secondary" onClick={() => onPageChange(pagination.page - 1)} disabled={pagination.page <= 1}>
|
|
175
|
+
Previous
|
|
176
|
+
</Button>
|
|
177
|
+
<Button size="sm" variant="secondary" onClick={() => onPageChange(pagination.page + 1)} disabled={pagination.page >= Math.ceil(pagination.total / pagination.size)}>
|
|
178
|
+
Next
|
|
179
|
+
</Button>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
99
183
|
</div>
|
|
100
184
|
);
|
|
101
185
|
}
|
|
102
186
|
```
|
|
103
187
|
|
|
104
|
-
|
|
188
|
+
### Step 5: Create Async Content Wrapper
|
|
189
|
+
```tsx
|
|
190
|
+
// src/components/ui/AsyncContent.tsx
|
|
191
|
+
import type { UseQueryResult } from '@tanstack/react-query';
|
|
105
192
|
|
|
106
|
-
|
|
193
|
+
interface AsyncContentProps<T> {
|
|
194
|
+
query: UseQueryResult<T>;
|
|
195
|
+
children: (data: T) => React.ReactNode;
|
|
196
|
+
}
|
|
107
197
|
|
|
108
|
-
|
|
109
|
-
function AsyncContent<T>({ query, children }: { query: UseQueryResult<T>, children: (data: T) => ReactNode }) {
|
|
198
|
+
export function AsyncContent<T>({ query, children }: AsyncContentProps<T>) {
|
|
110
199
|
if (query.isLoading) return <Skeleton />;
|
|
111
|
-
if (query.error) return <ErrorState message={query.error.message} />;
|
|
112
|
-
if (!query.data) return <EmptyState />;
|
|
200
|
+
if (query.error) return <ErrorState message={query.error.message} onRetry={query.refetch} />;
|
|
201
|
+
if (!query.data) return <EmptyState message="No data found" />;
|
|
113
202
|
return <>{children(query.data)}</>;
|
|
114
203
|
}
|
|
204
|
+
|
|
205
|
+
function Skeleton() {
|
|
206
|
+
return (
|
|
207
|
+
<div className="animate-pulse space-y-4">
|
|
208
|
+
<div className="h-4 bg-gray-200 rounded w-3/4" />
|
|
209
|
+
<div className="h-4 bg-gray-200 rounded w-1/2" />
|
|
210
|
+
<div className="h-4 bg-gray-200 rounded w-5/6" />
|
|
211
|
+
</div>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function ErrorState({ message, onRetry }: { message: string; onRetry?: () => void }) {
|
|
216
|
+
return (
|
|
217
|
+
<div className="text-center p-8">
|
|
218
|
+
<p className="text-red-600">{message}</p>
|
|
219
|
+
{onRetry && <Button variant="secondary" onClick={onRetry} className="mt-4">Retry</Button>}
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function EmptyState({ message }: { message: string }) {
|
|
225
|
+
return <div className="text-center p-8 text-gray-500">{message}</div>;
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Step 6: Verify Components
|
|
230
|
+
```bash
|
|
231
|
+
npm run dev
|
|
232
|
+
# Open http://localhost:5173 and visually verify components
|
|
233
|
+
|
|
234
|
+
npx tsc --noEmit
|
|
235
|
+
# Check for TypeScript errors
|
|
115
236
|
```
|
|
237
|
+
|
|
238
|
+
## Resources
|
|
239
|
+
- `references/tailwind-patterns.md` - Common Tailwind utility patterns
|
|
240
|
+
- `references/accessibility-checklist.md` - ARIA and keyboard nav requirements
|
|
241
|
+
|
|
242
|
+
## Examples
|
|
243
|
+
### Example 1: Create a Card Component
|
|
244
|
+
User asks: "Create a reusable card component with header, body, and footer slots"
|
|
245
|
+
Response approach:
|
|
246
|
+
1. Create a Card compound component with Card.Header, Card.Content, Card.Footer
|
|
247
|
+
2. Use Tailwind for styling with cn() for class merging
|
|
248
|
+
3. Add className prop pass-through for customization
|
|
249
|
+
4. Show usage example
|
|
250
|
+
|
|
251
|
+
### Example 2: Build a Status Dashboard Widget
|
|
252
|
+
User asks: "Create a metric card that shows a number with label and icon"
|
|
253
|
+
Response approach:
|
|
254
|
+
1. Create MetricCard with props: title, value, icon, trend
|
|
255
|
+
2. Style with Tailwind using responsive sizing
|
|
256
|
+
3. Add trend indicator (up/down arrow with color)
|
|
257
|
+
4. Show usage in a dashboard grid
|
|
258
|
+
|
|
259
|
+
## Notes
|
|
260
|
+
- Always extend native HTML attributes (React.ButtonHTMLAttributes, etc.)
|
|
261
|
+
- Use the cn() utility to merge Tailwind classes safely
|
|
262
|
+
- Every interactive element must be keyboard accessible
|
|
263
|
+
- Add aria-label to icon-only buttons
|
|
264
|
+
- Use `as const` for config objects to get literal type inference
|
|
265
|
+
- Test components in isolation before integrating into pages
|
package/templates/bundle-frontend-spa/skills/component-design/references/accessibility-checklist.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Accessibility Checklist
|
|
2
|
+
|
|
3
|
+
## Interactive Elements
|
|
4
|
+
- [ ] All buttons have visible text or `aria-label`
|
|
5
|
+
- [ ] Icon-only buttons have `aria-label` describing the action
|
|
6
|
+
- [ ] Links have descriptive text (not "click here")
|
|
7
|
+
- [ ] Focus states are visible (outline or ring)
|
|
8
|
+
- [ ] Tab order follows visual layout
|
|
9
|
+
|
|
10
|
+
## Forms
|
|
11
|
+
- [ ] Every input has a `<label>` with matching `htmlFor`/`id`
|
|
12
|
+
- [ ] Required fields are marked with `aria-required="true"`
|
|
13
|
+
- [ ] Error messages are linked with `aria-describedby`
|
|
14
|
+
- [ ] Form validation errors are announced to screen readers
|
|
15
|
+
|
|
16
|
+
## Modals/Dialogs
|
|
17
|
+
- [ ] Uses `role="dialog"` and `aria-modal="true"`
|
|
18
|
+
- [ ] Focus is trapped inside the dialog
|
|
19
|
+
- [ ] Escape key closes the dialog
|
|
20
|
+
- [ ] Focus returns to trigger element on close
|
|
21
|
+
|
|
22
|
+
## Loading States
|
|
23
|
+
- [ ] Loading spinners have `aria-busy="true"` on container
|
|
24
|
+
- [ ] Loading announcements use `aria-live="polite"`
|
|
25
|
+
|
|
26
|
+
## Images
|
|
27
|
+
- [ ] Decorative images have `alt=""`
|
|
28
|
+
- [ ] Informative images have descriptive `alt` text
|
|
29
|
+
|
|
30
|
+
## Color
|
|
31
|
+
- [ ] Text contrast ratio is at least 4.5:1 (normal text)
|
|
32
|
+
- [ ] Information is not conveyed by color alone
|
|
33
|
+
- [ ] Focus indicators have 3:1 contrast ratio
|
|
34
|
+
|
|
35
|
+
## Testing
|
|
36
|
+
```bash
|
|
37
|
+
# Run axe accessibility audit
|
|
38
|
+
npx @axe-core/cli http://localhost:5173
|
|
39
|
+
|
|
40
|
+
# Or in browser: install axe DevTools extension
|
|
41
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Tailwind CSS Common Patterns
|
|
2
|
+
|
|
3
|
+
## Flexbox Layouts
|
|
4
|
+
```html
|
|
5
|
+
<!-- Center content -->
|
|
6
|
+
<div class="flex items-center justify-center">
|
|
7
|
+
|
|
8
|
+
<!-- Space between items -->
|
|
9
|
+
<div class="flex items-center justify-between">
|
|
10
|
+
|
|
11
|
+
<!-- Stack vertically with gap -->
|
|
12
|
+
<div class="flex flex-col gap-4">
|
|
13
|
+
|
|
14
|
+
<!-- Inline items with wrap -->
|
|
15
|
+
<div class="flex flex-wrap gap-2">
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Grid Layouts
|
|
19
|
+
```html
|
|
20
|
+
<!-- Responsive grid -->
|
|
21
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
22
|
+
|
|
23
|
+
<!-- Sidebar + main -->
|
|
24
|
+
<div class="grid grid-cols-[250px_1fr]">
|
|
25
|
+
|
|
26
|
+
<!-- Auto-fill responsive -->
|
|
27
|
+
<div class="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] gap-4">
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Common Component Patterns
|
|
31
|
+
```html
|
|
32
|
+
<!-- Card -->
|
|
33
|
+
<div class="rounded-lg border bg-white shadow-sm p-4">
|
|
34
|
+
|
|
35
|
+
<!-- Badge -->
|
|
36
|
+
<span class="px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-700">
|
|
37
|
+
|
|
38
|
+
<!-- Input -->
|
|
39
|
+
<input class="w-full rounded border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" />
|
|
40
|
+
|
|
41
|
+
<!-- Overlay/Modal backdrop -->
|
|
42
|
+
<div class="fixed inset-0 bg-black/50 flex items-center justify-center">
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Animations
|
|
46
|
+
```html
|
|
47
|
+
<!-- Pulse (loading skeleton) -->
|
|
48
|
+
<div class="animate-pulse bg-gray-200 rounded h-4 w-3/4">
|
|
49
|
+
|
|
50
|
+
<!-- Spin (loading spinner) -->
|
|
51
|
+
<div class="animate-spin h-5 w-5 border-2 border-current border-t-transparent rounded-full">
|
|
52
|
+
|
|
53
|
+
<!-- Fade in -->
|
|
54
|
+
<div class="animate-in fade-in duration-200">
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Responsive Breakpoints
|
|
58
|
+
| Prefix | Min-width | Target |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| (none) | 0px | Mobile (default) |
|
|
61
|
+
| `sm:` | 640px | Landscape mobile |
|
|
62
|
+
| `md:` | 768px | Tablet |
|
|
63
|
+
| `lg:` | 1024px | Desktop |
|
|
64
|
+
| `xl:` | 1280px | Wide desktop |
|
|
65
|
+
| `2xl:` | 1536px | Ultra-wide |
|