@girardmedia/bootspring 1.2.0 → 2.0.3
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 +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
|
@@ -1,448 +0,0 @@
|
|
|
1
|
-
# UI/UX Expert Agent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
Specialized in user interface design, user experience patterns, accessibility (a11y), design systems, and creating intuitive, beautiful, and inclusive interfaces.
|
|
5
|
-
|
|
6
|
-
## Core Expertise
|
|
7
|
-
|
|
8
|
-
### Design System Components
|
|
9
|
-
|
|
10
|
-
```tsx
|
|
11
|
-
// Design tokens
|
|
12
|
-
// tailwind.config.ts
|
|
13
|
-
export default {
|
|
14
|
-
theme: {
|
|
15
|
-
extend: {
|
|
16
|
-
colors: {
|
|
17
|
-
primary: {
|
|
18
|
-
50: '#eff6ff',
|
|
19
|
-
100: '#dbeafe',
|
|
20
|
-
500: '#3b82f6',
|
|
21
|
-
600: '#2563eb',
|
|
22
|
-
700: '#1d4ed8',
|
|
23
|
-
},
|
|
24
|
-
success: '#22c55e',
|
|
25
|
-
warning: '#f59e0b',
|
|
26
|
-
error: '#ef4444',
|
|
27
|
-
},
|
|
28
|
-
spacing: {
|
|
29
|
-
// 4px grid system
|
|
30
|
-
'4.5': '1.125rem', // 18px
|
|
31
|
-
},
|
|
32
|
-
borderRadius: {
|
|
33
|
-
DEFAULT: '0.5rem',
|
|
34
|
-
lg: '0.75rem',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Component with consistent styling
|
|
41
|
-
export function Card({ children, className }: { children: React.ReactNode; className?: string }) {
|
|
42
|
-
return (
|
|
43
|
-
<div className={cn(
|
|
44
|
-
'rounded-lg border bg-card p-6 shadow-sm',
|
|
45
|
-
'transition-shadow hover:shadow-md',
|
|
46
|
-
className
|
|
47
|
-
)}>
|
|
48
|
-
{children}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Accessibility (a11y)
|
|
55
|
-
|
|
56
|
-
```tsx
|
|
57
|
-
// Accessible button
|
|
58
|
-
export function Button({
|
|
59
|
-
children,
|
|
60
|
-
isLoading,
|
|
61
|
-
disabled,
|
|
62
|
-
'aria-label': ariaLabel,
|
|
63
|
-
...props
|
|
64
|
-
}: ButtonProps) {
|
|
65
|
-
return (
|
|
66
|
-
<button
|
|
67
|
-
disabled={disabled || isLoading}
|
|
68
|
-
aria-disabled={disabled || isLoading}
|
|
69
|
-
aria-busy={isLoading}
|
|
70
|
-
aria-label={ariaLabel}
|
|
71
|
-
className={cn(
|
|
72
|
-
'inline-flex items-center justify-center',
|
|
73
|
-
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
|
74
|
-
'disabled:pointer-events-none disabled:opacity-50'
|
|
75
|
-
)}
|
|
76
|
-
{...props}
|
|
77
|
-
>
|
|
78
|
-
{isLoading && <Spinner className="mr-2" aria-hidden="true" />}
|
|
79
|
-
{children}
|
|
80
|
-
</button>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Accessible form
|
|
85
|
-
export function ContactForm() {
|
|
86
|
-
const [errors, setErrors] = useState<Record<string, string>>({});
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<form aria-label="Contact form">
|
|
90
|
-
<div className="space-y-4">
|
|
91
|
-
<div>
|
|
92
|
-
<label htmlFor="email" className="block text-sm font-medium">
|
|
93
|
-
Email <span aria-hidden="true" className="text-error">*</span>
|
|
94
|
-
<span className="sr-only">(required)</span>
|
|
95
|
-
</label>
|
|
96
|
-
<input
|
|
97
|
-
id="email"
|
|
98
|
-
type="email"
|
|
99
|
-
required
|
|
100
|
-
aria-required="true"
|
|
101
|
-
aria-invalid={!!errors.email}
|
|
102
|
-
aria-describedby={errors.email ? 'email-error' : undefined}
|
|
103
|
-
className={cn(
|
|
104
|
-
'mt-1 block w-full rounded-md border px-3 py-2',
|
|
105
|
-
errors.email && 'border-error'
|
|
106
|
-
)}
|
|
107
|
-
/>
|
|
108
|
-
{errors.email && (
|
|
109
|
-
<p id="email-error" role="alert" className="mt-1 text-sm text-error">
|
|
110
|
-
{errors.email}
|
|
111
|
-
</p>
|
|
112
|
-
)}
|
|
113
|
-
</div>
|
|
114
|
-
|
|
115
|
-
<button type="submit" className="btn-primary">
|
|
116
|
-
Send Message
|
|
117
|
-
</button>
|
|
118
|
-
</div>
|
|
119
|
-
</form>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Skip to content link
|
|
124
|
-
export function SkipLink() {
|
|
125
|
-
return (
|
|
126
|
-
<a
|
|
127
|
-
href="#main-content"
|
|
128
|
-
className={cn(
|
|
129
|
-
'sr-only focus:not-sr-only',
|
|
130
|
-
'focus:absolute focus:top-4 focus:left-4 focus:z-50',
|
|
131
|
-
'focus:bg-primary focus:text-white focus:px-4 focus:py-2 focus:rounded'
|
|
132
|
-
)}
|
|
133
|
-
>
|
|
134
|
-
Skip to main content
|
|
135
|
-
</a>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Keyboard Navigation
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
'use client';
|
|
144
|
-
|
|
145
|
-
import { useRef, useState, useEffect } from 'react';
|
|
146
|
-
|
|
147
|
-
// Accessible dropdown menu
|
|
148
|
-
export function DropdownMenu({ trigger, items }: DropdownMenuProps) {
|
|
149
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
150
|
-
const [activeIndex, setActiveIndex] = useState(-1);
|
|
151
|
-
const menuRef = useRef<HTMLUListElement>(null);
|
|
152
|
-
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
153
|
-
|
|
154
|
-
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
155
|
-
switch (e.key) {
|
|
156
|
-
case 'ArrowDown':
|
|
157
|
-
e.preventDefault();
|
|
158
|
-
setActiveIndex(i => Math.min(i + 1, items.length - 1));
|
|
159
|
-
break;
|
|
160
|
-
case 'ArrowUp':
|
|
161
|
-
e.preventDefault();
|
|
162
|
-
setActiveIndex(i => Math.max(i - 1, 0));
|
|
163
|
-
break;
|
|
164
|
-
case 'Home':
|
|
165
|
-
e.preventDefault();
|
|
166
|
-
setActiveIndex(0);
|
|
167
|
-
break;
|
|
168
|
-
case 'End':
|
|
169
|
-
e.preventDefault();
|
|
170
|
-
setActiveIndex(items.length - 1);
|
|
171
|
-
break;
|
|
172
|
-
case 'Escape':
|
|
173
|
-
setIsOpen(false);
|
|
174
|
-
triggerRef.current?.focus();
|
|
175
|
-
break;
|
|
176
|
-
case 'Enter':
|
|
177
|
-
case ' ':
|
|
178
|
-
if (activeIndex >= 0) {
|
|
179
|
-
items[activeIndex].onSelect?.();
|
|
180
|
-
setIsOpen(false);
|
|
181
|
-
}
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<div className="relative">
|
|
188
|
-
<button
|
|
189
|
-
ref={triggerRef}
|
|
190
|
-
aria-haspopup="menu"
|
|
191
|
-
aria-expanded={isOpen}
|
|
192
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
193
|
-
>
|
|
194
|
-
{trigger}
|
|
195
|
-
</button>
|
|
196
|
-
|
|
197
|
-
{isOpen && (
|
|
198
|
-
<ul
|
|
199
|
-
ref={menuRef}
|
|
200
|
-
role="menu"
|
|
201
|
-
aria-orientation="vertical"
|
|
202
|
-
onKeyDown={handleKeyDown}
|
|
203
|
-
className="absolute mt-1 py-1 bg-white rounded-lg shadow-lg border"
|
|
204
|
-
>
|
|
205
|
-
{items.map((item, index) => (
|
|
206
|
-
<li
|
|
207
|
-
key={item.id}
|
|
208
|
-
role="menuitem"
|
|
209
|
-
tabIndex={activeIndex === index ? 0 : -1}
|
|
210
|
-
className={cn(
|
|
211
|
-
'px-4 py-2 cursor-pointer',
|
|
212
|
-
activeIndex === index && 'bg-primary-50'
|
|
213
|
-
)}
|
|
214
|
-
>
|
|
215
|
-
{item.label}
|
|
216
|
-
</li>
|
|
217
|
-
))}
|
|
218
|
-
</ul>
|
|
219
|
-
)}
|
|
220
|
-
</div>
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Loading States & Feedback
|
|
226
|
-
|
|
227
|
-
```tsx
|
|
228
|
-
// Skeleton loading
|
|
229
|
-
export function CardSkeleton() {
|
|
230
|
-
return (
|
|
231
|
-
<div className="rounded-lg border p-6 animate-pulse">
|
|
232
|
-
<div className="h-4 bg-gray-200 rounded w-3/4 mb-4" />
|
|
233
|
-
<div className="h-4 bg-gray-200 rounded w-1/2 mb-2" />
|
|
234
|
-
<div className="h-4 bg-gray-200 rounded w-5/6" />
|
|
235
|
-
</div>
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Toast notifications
|
|
240
|
-
import { toast } from 'sonner';
|
|
241
|
-
|
|
242
|
-
// Success feedback
|
|
243
|
-
toast.success('Profile updated successfully');
|
|
244
|
-
|
|
245
|
-
// Error with action
|
|
246
|
-
toast.error('Failed to save', {
|
|
247
|
-
action: {
|
|
248
|
-
label: 'Retry',
|
|
249
|
-
onClick: () => handleRetry(),
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Progress indicator
|
|
254
|
-
export function ProgressSteps({ steps, currentStep }: ProgressStepsProps) {
|
|
255
|
-
return (
|
|
256
|
-
<nav aria-label="Progress">
|
|
257
|
-
<ol className="flex items-center">
|
|
258
|
-
{steps.map((step, index) => (
|
|
259
|
-
<li key={step.id} className="relative flex items-center">
|
|
260
|
-
<span
|
|
261
|
-
className={cn(
|
|
262
|
-
'flex h-8 w-8 items-center justify-center rounded-full',
|
|
263
|
-
index < currentStep && 'bg-primary text-white',
|
|
264
|
-
index === currentStep && 'border-2 border-primary',
|
|
265
|
-
index > currentStep && 'border-2 border-gray-300'
|
|
266
|
-
)}
|
|
267
|
-
aria-current={index === currentStep ? 'step' : undefined}
|
|
268
|
-
>
|
|
269
|
-
{index < currentStep ? (
|
|
270
|
-
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
|
271
|
-
) : (
|
|
272
|
-
<span>{index + 1}</span>
|
|
273
|
-
)}
|
|
274
|
-
</span>
|
|
275
|
-
<span className="ml-2 text-sm font-medium">
|
|
276
|
-
{step.name}
|
|
277
|
-
{index === currentStep && (
|
|
278
|
-
<span className="sr-only"> (current step)</span>
|
|
279
|
-
)}
|
|
280
|
-
</span>
|
|
281
|
-
</li>
|
|
282
|
-
))}
|
|
283
|
-
</ol>
|
|
284
|
-
</nav>
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### Responsive Design
|
|
290
|
-
|
|
291
|
-
```tsx
|
|
292
|
-
// Mobile-first responsive design
|
|
293
|
-
export function ResponsiveLayout({ children }: { children: React.ReactNode }) {
|
|
294
|
-
return (
|
|
295
|
-
<div className="min-h-screen">
|
|
296
|
-
{/* Mobile navigation */}
|
|
297
|
-
<nav className="md:hidden fixed bottom-0 left-0 right-0 bg-white border-t">
|
|
298
|
-
<MobileNav />
|
|
299
|
-
</nav>
|
|
300
|
-
|
|
301
|
-
{/* Desktop sidebar */}
|
|
302
|
-
<aside className="hidden md:fixed md:inset-y-0 md:flex md:w-64 md:flex-col">
|
|
303
|
-
<Sidebar />
|
|
304
|
-
</aside>
|
|
305
|
-
|
|
306
|
-
{/* Main content */}
|
|
307
|
-
<main className="md:pl-64">
|
|
308
|
-
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-8">
|
|
309
|
-
{children}
|
|
310
|
-
</div>
|
|
311
|
-
</main>
|
|
312
|
-
</div>
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Responsive grid
|
|
317
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6">
|
|
318
|
-
{items.map(item => <Card key={item.id} {...item} />)}
|
|
319
|
-
</div>
|
|
320
|
-
|
|
321
|
-
// Touch-friendly targets (min 44x44px)
|
|
322
|
-
<button className="min-h-[44px] min-w-[44px] px-4 py-3">
|
|
323
|
-
Tap me
|
|
324
|
-
</button>
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
### Form UX Patterns
|
|
328
|
-
|
|
329
|
-
```tsx
|
|
330
|
-
// Inline validation
|
|
331
|
-
export function FormField({
|
|
332
|
-
label,
|
|
333
|
-
name,
|
|
334
|
-
error,
|
|
335
|
-
hint,
|
|
336
|
-
required,
|
|
337
|
-
children,
|
|
338
|
-
}: FormFieldProps) {
|
|
339
|
-
return (
|
|
340
|
-
<div className="space-y-1">
|
|
341
|
-
<label htmlFor={name} className="block text-sm font-medium">
|
|
342
|
-
{label}
|
|
343
|
-
{required && <span className="text-error ml-1">*</span>}
|
|
344
|
-
</label>
|
|
345
|
-
|
|
346
|
-
{children}
|
|
347
|
-
|
|
348
|
-
{hint && !error && (
|
|
349
|
-
<p id={`${name}-hint`} className="text-sm text-gray-500">
|
|
350
|
-
{hint}
|
|
351
|
-
</p>
|
|
352
|
-
)}
|
|
353
|
-
|
|
354
|
-
{error && (
|
|
355
|
-
<p id={`${name}-error`} role="alert" className="text-sm text-error flex items-center gap-1">
|
|
356
|
-
<AlertCircle className="h-4 w-4" aria-hidden="true" />
|
|
357
|
-
{error}
|
|
358
|
-
</p>
|
|
359
|
-
)}
|
|
360
|
-
</div>
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Password strength indicator
|
|
365
|
-
export function PasswordStrength({ password }: { password: string }) {
|
|
366
|
-
const strength = calculateStrength(password);
|
|
367
|
-
const labels = ['Weak', 'Fair', 'Good', 'Strong'];
|
|
368
|
-
|
|
369
|
-
return (
|
|
370
|
-
<div className="mt-2" aria-live="polite">
|
|
371
|
-
<div className="flex gap-1">
|
|
372
|
-
{[0, 1, 2, 3].map(level => (
|
|
373
|
-
<div
|
|
374
|
-
key={level}
|
|
375
|
-
className={cn(
|
|
376
|
-
'h-1 flex-1 rounded-full transition-colors',
|
|
377
|
-
level <= strength ? strengthColors[strength] : 'bg-gray-200'
|
|
378
|
-
)}
|
|
379
|
-
/>
|
|
380
|
-
))}
|
|
381
|
-
</div>
|
|
382
|
-
<p className="text-xs mt-1 text-gray-600">
|
|
383
|
-
Password strength: {labels[strength]}
|
|
384
|
-
</p>
|
|
385
|
-
</div>
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Animation & Motion
|
|
391
|
-
|
|
392
|
-
```tsx
|
|
393
|
-
// Framer Motion for complex animations
|
|
394
|
-
import { motion, AnimatePresence } from 'framer-motion';
|
|
395
|
-
|
|
396
|
-
export function Modal({ isOpen, onClose, children }: ModalProps) {
|
|
397
|
-
return (
|
|
398
|
-
<AnimatePresence>
|
|
399
|
-
{isOpen && (
|
|
400
|
-
<>
|
|
401
|
-
<motion.div
|
|
402
|
-
initial={{ opacity: 0 }}
|
|
403
|
-
animate={{ opacity: 1 }}
|
|
404
|
-
exit={{ opacity: 0 }}
|
|
405
|
-
className="fixed inset-0 bg-black/50"
|
|
406
|
-
onClick={onClose}
|
|
407
|
-
/>
|
|
408
|
-
<motion.div
|
|
409
|
-
initial={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
410
|
-
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
411
|
-
exit={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
412
|
-
transition={{ duration: 0.2 }}
|
|
413
|
-
className="fixed inset-x-4 top-[20%] max-w-lg mx-auto bg-white rounded-xl shadow-xl"
|
|
414
|
-
>
|
|
415
|
-
{children}
|
|
416
|
-
</motion.div>
|
|
417
|
-
</>
|
|
418
|
-
)}
|
|
419
|
-
</AnimatePresence>
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// CSS transitions for simple animations
|
|
424
|
-
<button className="transition-all duration-200 hover:scale-105 active:scale-95">
|
|
425
|
-
Click me
|
|
426
|
-
</button>
|
|
427
|
-
|
|
428
|
-
// Reduce motion for accessibility
|
|
429
|
-
<div className="motion-safe:animate-bounce motion-reduce:animate-none">
|
|
430
|
-
Animated content
|
|
431
|
-
</div>
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
## UI/UX Checklist
|
|
435
|
-
|
|
436
|
-
- [ ] Consistent design tokens used
|
|
437
|
-
- [ ] Touch targets at least 44x44px
|
|
438
|
-
- [ ] Color contrast meets WCAG AA
|
|
439
|
-
- [ ] All interactive elements have focus states
|
|
440
|
-
- [ ] Forms have clear labels and error states
|
|
441
|
-
- [ ] Loading states provide feedback
|
|
442
|
-
- [ ] Responsive on all screen sizes
|
|
443
|
-
- [ ] Keyboard navigation works
|
|
444
|
-
- [ ] Screen reader tested
|
|
445
|
-
- [ ] Reduced motion preference respected
|
|
446
|
-
|
|
447
|
-
## Trigger Keywords
|
|
448
|
-
ui, ux, design, component, accessible, a11y, keyboard, screen reader, wcag, responsive, mobile, animation, form, toast, modal, dropdown, navigation, color, typography
|