@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,395 +0,0 @@
|
|
|
1
|
-
# Accordion Patterns
|
|
2
|
-
|
|
3
|
-
Patterns for collapsible accordion components.
|
|
4
|
-
|
|
5
|
-
## Radix Accordion
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
// components/ui/Accordion.tsx
|
|
9
|
-
'use client'
|
|
10
|
-
|
|
11
|
-
import * as AccordionPrimitive from '@radix-ui/react-accordion'
|
|
12
|
-
import { ChevronDown } from 'lucide-react'
|
|
13
|
-
import { forwardRef } from 'react'
|
|
14
|
-
import { cn } from '@/lib/utils'
|
|
15
|
-
|
|
16
|
-
export const Accordion = AccordionPrimitive.Root
|
|
17
|
-
|
|
18
|
-
export const AccordionItem = forwardRef<
|
|
19
|
-
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
20
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
|
21
|
-
>(({ className, ...props }, ref) => (
|
|
22
|
-
<AccordionPrimitive.Item
|
|
23
|
-
ref={ref}
|
|
24
|
-
className={cn('border-b', className)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
))
|
|
28
|
-
AccordionItem.displayName = 'AccordionItem'
|
|
29
|
-
|
|
30
|
-
export const AccordionTrigger = forwardRef<
|
|
31
|
-
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
32
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
33
|
-
>(({ className, children, ...props }, ref) => (
|
|
34
|
-
<AccordionPrimitive.Header className="flex">
|
|
35
|
-
<AccordionPrimitive.Trigger
|
|
36
|
-
ref={ref}
|
|
37
|
-
className={cn(
|
|
38
|
-
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline',
|
|
39
|
-
'[&[data-state=open]>svg]:rotate-180',
|
|
40
|
-
className
|
|
41
|
-
)}
|
|
42
|
-
{...props}
|
|
43
|
-
>
|
|
44
|
-
{children}
|
|
45
|
-
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
|
46
|
-
</AccordionPrimitive.Trigger>
|
|
47
|
-
</AccordionPrimitive.Header>
|
|
48
|
-
))
|
|
49
|
-
AccordionTrigger.displayName = 'AccordionTrigger'
|
|
50
|
-
|
|
51
|
-
export const AccordionContent = forwardRef<
|
|
52
|
-
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
53
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
54
|
-
>(({ className, children, ...props }, ref) => (
|
|
55
|
-
<AccordionPrimitive.Content
|
|
56
|
-
ref={ref}
|
|
57
|
-
className={cn(
|
|
58
|
-
'overflow-hidden text-sm transition-all',
|
|
59
|
-
'data-[state=closed]:animate-accordion-up',
|
|
60
|
-
'data-[state=open]:animate-accordion-down',
|
|
61
|
-
className
|
|
62
|
-
)}
|
|
63
|
-
{...props}
|
|
64
|
-
>
|
|
65
|
-
<div className="pb-4 pt-0">{children}</div>
|
|
66
|
-
</AccordionPrimitive.Content>
|
|
67
|
-
))
|
|
68
|
-
AccordionContent.displayName = 'AccordionContent'
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Tailwind Animation Config
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
// tailwind.config.js
|
|
75
|
-
module.exports = {
|
|
76
|
-
theme: {
|
|
77
|
-
extend: {
|
|
78
|
-
keyframes: {
|
|
79
|
-
'accordion-down': {
|
|
80
|
-
from: { height: '0' },
|
|
81
|
-
to: { height: 'var(--radix-accordion-content-height)' }
|
|
82
|
-
},
|
|
83
|
-
'accordion-up': {
|
|
84
|
-
from: { height: 'var(--radix-accordion-content-height)' },
|
|
85
|
-
to: { height: '0' }
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
animation: {
|
|
89
|
-
'accordion-down': 'accordion-down 0.2s ease-out',
|
|
90
|
-
'accordion-up': 'accordion-up 0.2s ease-out'
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## FAQ Accordion
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
// components/FAQ.tsx
|
|
101
|
-
import {
|
|
102
|
-
Accordion,
|
|
103
|
-
AccordionContent,
|
|
104
|
-
AccordionItem,
|
|
105
|
-
AccordionTrigger
|
|
106
|
-
} from '@/components/ui/Accordion'
|
|
107
|
-
|
|
108
|
-
const faqs = [
|
|
109
|
-
{
|
|
110
|
-
question: 'How do I get started?',
|
|
111
|
-
answer: 'Sign up for a free account and follow our getting started guide.'
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
question: 'What payment methods do you accept?',
|
|
115
|
-
answer: 'We accept all major credit cards, PayPal, and bank transfers.'
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
question: 'Can I cancel my subscription?',
|
|
119
|
-
answer: 'Yes, you can cancel anytime. Your account will remain active until the end of your billing period.'
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
question: 'Do you offer refunds?',
|
|
123
|
-
answer: 'We offer a 30-day money-back guarantee for all paid plans.'
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
|
|
127
|
-
export function FAQ() {
|
|
128
|
-
return (
|
|
129
|
-
<section className="py-16">
|
|
130
|
-
<div className="container max-w-3xl">
|
|
131
|
-
<h2 className="mb-8 text-center text-3xl font-bold">
|
|
132
|
-
Frequently Asked Questions
|
|
133
|
-
</h2>
|
|
134
|
-
|
|
135
|
-
<Accordion type="single" collapsible className="w-full">
|
|
136
|
-
{faqs.map((faq, index) => (
|
|
137
|
-
<AccordionItem key={index} value={`item-${index}`}>
|
|
138
|
-
<AccordionTrigger>{faq.question}</AccordionTrigger>
|
|
139
|
-
<AccordionContent>{faq.answer}</AccordionContent>
|
|
140
|
-
</AccordionItem>
|
|
141
|
-
))}
|
|
142
|
-
</Accordion>
|
|
143
|
-
</div>
|
|
144
|
-
</section>
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Multiple Open Accordion
|
|
150
|
-
|
|
151
|
-
```tsx
|
|
152
|
-
// components/SettingsAccordion.tsx
|
|
153
|
-
import {
|
|
154
|
-
Accordion,
|
|
155
|
-
AccordionContent,
|
|
156
|
-
AccordionItem,
|
|
157
|
-
AccordionTrigger
|
|
158
|
-
} from '@/components/ui/Accordion'
|
|
159
|
-
import { User, Bell, Shield, CreditCard } from 'lucide-react'
|
|
160
|
-
|
|
161
|
-
export function SettingsAccordion() {
|
|
162
|
-
return (
|
|
163
|
-
<Accordion type="multiple" className="w-full" defaultValue={['profile']}>
|
|
164
|
-
<AccordionItem value="profile">
|
|
165
|
-
<AccordionTrigger>
|
|
166
|
-
<div className="flex items-center gap-2">
|
|
167
|
-
<User className="h-4 w-4" />
|
|
168
|
-
Profile Settings
|
|
169
|
-
</div>
|
|
170
|
-
</AccordionTrigger>
|
|
171
|
-
<AccordionContent>
|
|
172
|
-
<div className="space-y-4">
|
|
173
|
-
<div>
|
|
174
|
-
<label className="text-sm font-medium">Display Name</label>
|
|
175
|
-
<input
|
|
176
|
-
type="text"
|
|
177
|
-
className="mt-1 w-full rounded border px-3 py-2"
|
|
178
|
-
/>
|
|
179
|
-
</div>
|
|
180
|
-
<div>
|
|
181
|
-
<label className="text-sm font-medium">Bio</label>
|
|
182
|
-
<textarea className="mt-1 w-full rounded border px-3 py-2" />
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
</AccordionContent>
|
|
186
|
-
</AccordionItem>
|
|
187
|
-
|
|
188
|
-
<AccordionItem value="notifications">
|
|
189
|
-
<AccordionTrigger>
|
|
190
|
-
<div className="flex items-center gap-2">
|
|
191
|
-
<Bell className="h-4 w-4" />
|
|
192
|
-
Notifications
|
|
193
|
-
</div>
|
|
194
|
-
</AccordionTrigger>
|
|
195
|
-
<AccordionContent>
|
|
196
|
-
<div className="space-y-3">
|
|
197
|
-
<label className="flex items-center gap-2">
|
|
198
|
-
<input type="checkbox" defaultChecked />
|
|
199
|
-
<span>Email notifications</span>
|
|
200
|
-
</label>
|
|
201
|
-
<label className="flex items-center gap-2">
|
|
202
|
-
<input type="checkbox" defaultChecked />
|
|
203
|
-
<span>Push notifications</span>
|
|
204
|
-
</label>
|
|
205
|
-
<label className="flex items-center gap-2">
|
|
206
|
-
<input type="checkbox" />
|
|
207
|
-
<span>SMS notifications</span>
|
|
208
|
-
</label>
|
|
209
|
-
</div>
|
|
210
|
-
</AccordionContent>
|
|
211
|
-
</AccordionItem>
|
|
212
|
-
|
|
213
|
-
<AccordionItem value="security">
|
|
214
|
-
<AccordionTrigger>
|
|
215
|
-
<div className="flex items-center gap-2">
|
|
216
|
-
<Shield className="h-4 w-4" />
|
|
217
|
-
Security
|
|
218
|
-
</div>
|
|
219
|
-
</AccordionTrigger>
|
|
220
|
-
<AccordionContent>
|
|
221
|
-
<div className="space-y-4">
|
|
222
|
-
<button className="rounded bg-blue-600 px-4 py-2 text-white">
|
|
223
|
-
Change Password
|
|
224
|
-
</button>
|
|
225
|
-
<button className="rounded border px-4 py-2">
|
|
226
|
-
Enable Two-Factor Auth
|
|
227
|
-
</button>
|
|
228
|
-
</div>
|
|
229
|
-
</AccordionContent>
|
|
230
|
-
</AccordionItem>
|
|
231
|
-
|
|
232
|
-
<AccordionItem value="billing">
|
|
233
|
-
<AccordionTrigger>
|
|
234
|
-
<div className="flex items-center gap-2">
|
|
235
|
-
<CreditCard className="h-4 w-4" />
|
|
236
|
-
Billing
|
|
237
|
-
</div>
|
|
238
|
-
</AccordionTrigger>
|
|
239
|
-
<AccordionContent>
|
|
240
|
-
<div className="space-y-4">
|
|
241
|
-
<div className="rounded bg-gray-50 p-4">
|
|
242
|
-
<p className="font-medium">Current Plan: Pro</p>
|
|
243
|
-
<p className="text-sm text-gray-600">$29/month</p>
|
|
244
|
-
</div>
|
|
245
|
-
<button className="text-sm text-blue-600 hover:underline">
|
|
246
|
-
View billing history
|
|
247
|
-
</button>
|
|
248
|
-
</div>
|
|
249
|
-
</AccordionContent>
|
|
250
|
-
</AccordionItem>
|
|
251
|
-
</Accordion>
|
|
252
|
-
)
|
|
253
|
-
}
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Controlled Accordion
|
|
257
|
-
|
|
258
|
-
```tsx
|
|
259
|
-
// components/ControlledAccordion.tsx
|
|
260
|
-
'use client'
|
|
261
|
-
|
|
262
|
-
import { useState } from 'react'
|
|
263
|
-
import {
|
|
264
|
-
Accordion,
|
|
265
|
-
AccordionContent,
|
|
266
|
-
AccordionItem,
|
|
267
|
-
AccordionTrigger
|
|
268
|
-
} from '@/components/ui/Accordion'
|
|
269
|
-
|
|
270
|
-
export function ControlledAccordion() {
|
|
271
|
-
const [openItems, setOpenItems] = useState<string[]>(['item-1'])
|
|
272
|
-
|
|
273
|
-
const expandAll = () => {
|
|
274
|
-
setOpenItems(['item-1', 'item-2', 'item-3'])
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const collapseAll = () => {
|
|
278
|
-
setOpenItems([])
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return (
|
|
282
|
-
<div>
|
|
283
|
-
<div className="mb-4 flex gap-2">
|
|
284
|
-
<button
|
|
285
|
-
onClick={expandAll}
|
|
286
|
-
className="text-sm text-blue-600 hover:underline"
|
|
287
|
-
>
|
|
288
|
-
Expand All
|
|
289
|
-
</button>
|
|
290
|
-
<button
|
|
291
|
-
onClick={collapseAll}
|
|
292
|
-
className="text-sm text-blue-600 hover:underline"
|
|
293
|
-
>
|
|
294
|
-
Collapse All
|
|
295
|
-
</button>
|
|
296
|
-
</div>
|
|
297
|
-
|
|
298
|
-
<Accordion
|
|
299
|
-
type="multiple"
|
|
300
|
-
value={openItems}
|
|
301
|
-
onValueChange={setOpenItems}
|
|
302
|
-
>
|
|
303
|
-
<AccordionItem value="item-1">
|
|
304
|
-
<AccordionTrigger>Section 1</AccordionTrigger>
|
|
305
|
-
<AccordionContent>Content for section 1</AccordionContent>
|
|
306
|
-
</AccordionItem>
|
|
307
|
-
<AccordionItem value="item-2">
|
|
308
|
-
<AccordionTrigger>Section 2</AccordionTrigger>
|
|
309
|
-
<AccordionContent>Content for section 2</AccordionContent>
|
|
310
|
-
</AccordionItem>
|
|
311
|
-
<AccordionItem value="item-3">
|
|
312
|
-
<AccordionTrigger>Section 3</AccordionTrigger>
|
|
313
|
-
<AccordionContent>Content for section 3</AccordionContent>
|
|
314
|
-
</AccordionItem>
|
|
315
|
-
</Accordion>
|
|
316
|
-
</div>
|
|
317
|
-
)
|
|
318
|
-
}
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## Nested Accordion
|
|
322
|
-
|
|
323
|
-
```tsx
|
|
324
|
-
// components/NestedAccordion.tsx
|
|
325
|
-
import {
|
|
326
|
-
Accordion,
|
|
327
|
-
AccordionContent,
|
|
328
|
-
AccordionItem,
|
|
329
|
-
AccordionTrigger
|
|
330
|
-
} from '@/components/ui/Accordion'
|
|
331
|
-
|
|
332
|
-
interface Category {
|
|
333
|
-
name: string
|
|
334
|
-
subcategories: {
|
|
335
|
-
name: string
|
|
336
|
-
items: string[]
|
|
337
|
-
}[]
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const categories: Category[] = [
|
|
341
|
-
{
|
|
342
|
-
name: 'Electronics',
|
|
343
|
-
subcategories: [
|
|
344
|
-
{ name: 'Phones', items: ['iPhone', 'Samsung', 'Google Pixel'] },
|
|
345
|
-
{ name: 'Laptops', items: ['MacBook', 'ThinkPad', 'XPS'] }
|
|
346
|
-
]
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
name: 'Clothing',
|
|
350
|
-
subcategories: [
|
|
351
|
-
{ name: 'Men', items: ['Shirts', 'Pants', 'Shoes'] },
|
|
352
|
-
{ name: 'Women', items: ['Dresses', 'Tops', 'Accessories'] }
|
|
353
|
-
]
|
|
354
|
-
}
|
|
355
|
-
]
|
|
356
|
-
|
|
357
|
-
export function NestedAccordion() {
|
|
358
|
-
return (
|
|
359
|
-
<Accordion type="single" collapsible>
|
|
360
|
-
{categories.map((category, i) => (
|
|
361
|
-
<AccordionItem key={i} value={`category-${i}`}>
|
|
362
|
-
<AccordionTrigger className="text-lg font-semibold">
|
|
363
|
-
{category.name}
|
|
364
|
-
</AccordionTrigger>
|
|
365
|
-
<AccordionContent>
|
|
366
|
-
<Accordion type="single" collapsible className="ml-4">
|
|
367
|
-
{category.subcategories.map((sub, j) => (
|
|
368
|
-
<AccordionItem key={j} value={`sub-${i}-${j}`}>
|
|
369
|
-
<AccordionTrigger>{sub.name}</AccordionTrigger>
|
|
370
|
-
<AccordionContent>
|
|
371
|
-
<ul className="ml-4 list-disc space-y-1">
|
|
372
|
-
{sub.items.map((item, k) => (
|
|
373
|
-
<li key={k} className="text-gray-600">
|
|
374
|
-
{item}
|
|
375
|
-
</li>
|
|
376
|
-
))}
|
|
377
|
-
</ul>
|
|
378
|
-
</AccordionContent>
|
|
379
|
-
</AccordionItem>
|
|
380
|
-
))}
|
|
381
|
-
</Accordion>
|
|
382
|
-
</AccordionContent>
|
|
383
|
-
</AccordionItem>
|
|
384
|
-
))}
|
|
385
|
-
</Accordion>
|
|
386
|
-
)
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
## When to Use
|
|
391
|
-
|
|
392
|
-
- FAQ sections
|
|
393
|
-
- Settings panels
|
|
394
|
-
- Navigation menus
|
|
395
|
-
- Collapsible content
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
# Card Patterns
|
|
2
|
-
|
|
3
|
-
Patterns for building card components.
|
|
4
|
-
|
|
5
|
-
## Basic Card
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
// components/ui/Card.tsx
|
|
9
|
-
interface CardProps {
|
|
10
|
-
children: React.ReactNode
|
|
11
|
-
className?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function Card({ children, className = '' }: CardProps) {
|
|
15
|
-
return (
|
|
16
|
-
<div className={`rounded-lg border bg-white p-6 shadow-sm ${className}`}>
|
|
17
|
-
{children}
|
|
18
|
-
</div>
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function CardHeader({ children }: { children: React.ReactNode }) {
|
|
23
|
-
return <div className="mb-4">{children}</div>
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function CardTitle({ children }: { children: React.ReactNode }) {
|
|
27
|
-
return <h3 className="text-lg font-semibold">{children}</h3>
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function CardDescription({ children }: { children: React.ReactNode }) {
|
|
31
|
-
return <p className="text-sm text-gray-500">{children}</p>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function CardContent({ children }: { children: React.ReactNode }) {
|
|
35
|
-
return <div>{children}</div>
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function CardFooter({ children }: { children: React.ReactNode }) {
|
|
39
|
-
return <div className="mt-4 flex items-center gap-2">{children}</div>
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Usage
|
|
43
|
-
<Card>
|
|
44
|
-
<CardHeader>
|
|
45
|
-
<CardTitle>Card Title</CardTitle>
|
|
46
|
-
<CardDescription>Card description here</CardDescription>
|
|
47
|
-
</CardHeader>
|
|
48
|
-
<CardContent>
|
|
49
|
-
<p>Card content</p>
|
|
50
|
-
</CardContent>
|
|
51
|
-
<CardFooter>
|
|
52
|
-
<button>Action</button>
|
|
53
|
-
</CardFooter>
|
|
54
|
-
</Card>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Interactive Card
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
// components/ui/InteractiveCard.tsx
|
|
61
|
-
import Link from 'next/link'
|
|
62
|
-
|
|
63
|
-
interface Props {
|
|
64
|
-
href: string
|
|
65
|
-
title: string
|
|
66
|
-
description: string
|
|
67
|
-
icon?: React.ReactNode
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function InteractiveCard({ href, title, description, icon }: Props) {
|
|
71
|
-
return (
|
|
72
|
-
<Link
|
|
73
|
-
href={href}
|
|
74
|
-
className="group block rounded-lg border p-6 transition-all hover:border-gray-300 hover:shadow-md"
|
|
75
|
-
>
|
|
76
|
-
{icon && (
|
|
77
|
-
<div className="mb-4 inline-block rounded-lg bg-gray-100 p-3 group-hover:bg-gray-200">
|
|
78
|
-
{icon}
|
|
79
|
-
</div>
|
|
80
|
-
)}
|
|
81
|
-
<h3 className="font-semibold group-hover:text-blue-600">{title}</h3>
|
|
82
|
-
<p className="mt-2 text-sm text-gray-500">{description}</p>
|
|
83
|
-
</Link>
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Stats Card
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
// components/cards/StatsCard.tsx
|
|
92
|
-
import { ArrowUp, ArrowDown } from 'lucide-react'
|
|
93
|
-
|
|
94
|
-
interface Props {
|
|
95
|
-
title: string
|
|
96
|
-
value: string | number
|
|
97
|
-
change?: number
|
|
98
|
-
changeLabel?: string
|
|
99
|
-
icon?: React.ReactNode
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function StatsCard({ title, value, change, changeLabel, icon }: Props) {
|
|
103
|
-
const isPositive = change && change > 0
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
<div className="rounded-lg border bg-white p-6">
|
|
107
|
-
<div className="flex items-center justify-between">
|
|
108
|
-
<p className="text-sm font-medium text-gray-500">{title}</p>
|
|
109
|
-
{icon && <div className="text-gray-400">{icon}</div>}
|
|
110
|
-
</div>
|
|
111
|
-
|
|
112
|
-
<p className="mt-2 text-3xl font-bold">{value}</p>
|
|
113
|
-
|
|
114
|
-
{change !== undefined && (
|
|
115
|
-
<div className="mt-2 flex items-center gap-1">
|
|
116
|
-
<span className={`flex items-center text-sm ${
|
|
117
|
-
isPositive ? 'text-green-600' : 'text-red-600'
|
|
118
|
-
}`}>
|
|
119
|
-
{isPositive ? <ArrowUp className="h-4 w-4" /> : <ArrowDown className="h-4 w-4" />}
|
|
120
|
-
{Math.abs(change)}%
|
|
121
|
-
</span>
|
|
122
|
-
{changeLabel && (
|
|
123
|
-
<span className="text-sm text-gray-500">{changeLabel}</span>
|
|
124
|
-
)}
|
|
125
|
-
</div>
|
|
126
|
-
)}
|
|
127
|
-
</div>
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Usage
|
|
132
|
-
<div className="grid gap-4 md:grid-cols-4">
|
|
133
|
-
<StatsCard title="Revenue" value="$45,231" change={12.5} changeLabel="from last month" />
|
|
134
|
-
<StatsCard title="Users" value="2,345" change={-3.2} changeLabel="from last month" />
|
|
135
|
-
<StatsCard title="Orders" value="1,234" change={8.1} changeLabel="from last month" />
|
|
136
|
-
<StatsCard title="Conversion" value="3.2%" change={1.2} changeLabel="from last month" />
|
|
137
|
-
</div>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Feature Card
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
// components/cards/FeatureCard.tsx
|
|
144
|
-
interface Props {
|
|
145
|
-
icon: React.ReactNode
|
|
146
|
-
title: string
|
|
147
|
-
description: string
|
|
148
|
-
features: string[]
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function FeatureCard({ icon, title, description, features }: Props) {
|
|
152
|
-
return (
|
|
153
|
-
<div className="rounded-xl border bg-white p-8">
|
|
154
|
-
<div className="mb-4 inline-block rounded-lg bg-blue-100 p-3 text-blue-600">
|
|
155
|
-
{icon}
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<h3 className="mb-2 text-xl font-semibold">{title}</h3>
|
|
159
|
-
<p className="mb-4 text-gray-600">{description}</p>
|
|
160
|
-
|
|
161
|
-
<ul className="space-y-2">
|
|
162
|
-
{features.map((feature, i) => (
|
|
163
|
-
<li key={i} className="flex items-center gap-2 text-sm">
|
|
164
|
-
<svg className="h-4 w-4 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
|
165
|
-
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
|
166
|
-
</svg>
|
|
167
|
-
{feature}
|
|
168
|
-
</li>
|
|
169
|
-
))}
|
|
170
|
-
</ul>
|
|
171
|
-
</div>
|
|
172
|
-
)
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Pricing Card
|
|
177
|
-
|
|
178
|
-
```tsx
|
|
179
|
-
// components/cards/PricingCard.tsx
|
|
180
|
-
interface Props {
|
|
181
|
-
name: string
|
|
182
|
-
price: number
|
|
183
|
-
period?: string
|
|
184
|
-
description: string
|
|
185
|
-
features: string[]
|
|
186
|
-
highlighted?: boolean
|
|
187
|
-
ctaText?: string
|
|
188
|
-
onSelect: () => void
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export function PricingCard({
|
|
192
|
-
name,
|
|
193
|
-
price,
|
|
194
|
-
period = '/month',
|
|
195
|
-
description,
|
|
196
|
-
features,
|
|
197
|
-
highlighted = false,
|
|
198
|
-
ctaText = 'Get Started',
|
|
199
|
-
onSelect
|
|
200
|
-
}: Props) {
|
|
201
|
-
return (
|
|
202
|
-
<div className={`relative rounded-2xl p-8 ${
|
|
203
|
-
highlighted
|
|
204
|
-
? 'border-2 border-blue-600 bg-white shadow-xl'
|
|
205
|
-
: 'border bg-white'
|
|
206
|
-
}`}>
|
|
207
|
-
{highlighted && (
|
|
208
|
-
<div className="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-blue-600 px-3 py-1 text-xs font-medium text-white">
|
|
209
|
-
Most Popular
|
|
210
|
-
</div>
|
|
211
|
-
)}
|
|
212
|
-
|
|
213
|
-
<h3 className="text-lg font-semibold">{name}</h3>
|
|
214
|
-
<p className="mt-2 text-sm text-gray-500">{description}</p>
|
|
215
|
-
|
|
216
|
-
<div className="my-6">
|
|
217
|
-
<span className="text-4xl font-bold">${price}</span>
|
|
218
|
-
<span className="text-gray-500">{period}</span>
|
|
219
|
-
</div>
|
|
220
|
-
|
|
221
|
-
<ul className="mb-8 space-y-3">
|
|
222
|
-
{features.map((feature, i) => (
|
|
223
|
-
<li key={i} className="flex items-center gap-2 text-sm">
|
|
224
|
-
<svg className="h-5 w-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
225
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
226
|
-
</svg>
|
|
227
|
-
{feature}
|
|
228
|
-
</li>
|
|
229
|
-
))}
|
|
230
|
-
</ul>
|
|
231
|
-
|
|
232
|
-
<button
|
|
233
|
-
onClick={onSelect}
|
|
234
|
-
className={`w-full rounded-lg py-3 font-medium ${
|
|
235
|
-
highlighted
|
|
236
|
-
? 'bg-blue-600 text-white hover:bg-blue-700'
|
|
237
|
-
: 'bg-gray-100 text-gray-900 hover:bg-gray-200'
|
|
238
|
-
}`}
|
|
239
|
-
>
|
|
240
|
-
{ctaText}
|
|
241
|
-
</button>
|
|
242
|
-
</div>
|
|
243
|
-
)
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## User Card
|
|
248
|
-
|
|
249
|
-
```tsx
|
|
250
|
-
// components/cards/UserCard.tsx
|
|
251
|
-
import Image from 'next/image'
|
|
252
|
-
|
|
253
|
-
interface Props {
|
|
254
|
-
user: {
|
|
255
|
-
name: string
|
|
256
|
-
email: string
|
|
257
|
-
avatar?: string
|
|
258
|
-
role: string
|
|
259
|
-
}
|
|
260
|
-
actions?: React.ReactNode
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export function UserCard({ user, actions }: Props) {
|
|
264
|
-
return (
|
|
265
|
-
<div className="flex items-center justify-between rounded-lg border p-4">
|
|
266
|
-
<div className="flex items-center gap-4">
|
|
267
|
-
<div className="relative h-12 w-12 overflow-hidden rounded-full bg-gray-200">
|
|
268
|
-
{user.avatar ? (
|
|
269
|
-
<Image src={user.avatar} alt={user.name} fill className="object-cover" />
|
|
270
|
-
) : (
|
|
271
|
-
<div className="flex h-full w-full items-center justify-center text-lg font-medium text-gray-600">
|
|
272
|
-
{user.name.charAt(0)}
|
|
273
|
-
</div>
|
|
274
|
-
)}
|
|
275
|
-
</div>
|
|
276
|
-
|
|
277
|
-
<div>
|
|
278
|
-
<p className="font-medium">{user.name}</p>
|
|
279
|
-
<p className="text-sm text-gray-500">{user.email}</p>
|
|
280
|
-
</div>
|
|
281
|
-
</div>
|
|
282
|
-
|
|
283
|
-
<div className="flex items-center gap-4">
|
|
284
|
-
<span className="rounded-full bg-gray-100 px-3 py-1 text-xs font-medium">
|
|
285
|
-
{user.role}
|
|
286
|
-
</span>
|
|
287
|
-
{actions}
|
|
288
|
-
</div>
|
|
289
|
-
</div>
|
|
290
|
-
)
|
|
291
|
-
}
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
## When to Use
|
|
295
|
-
|
|
296
|
-
- Content display
|
|
297
|
-
- Feature highlights
|
|
298
|
-
- Pricing tables
|
|
299
|
-
- User lists
|