@vadimcomanescu/nadicode-design-system 4.0.0 → 4.0.2
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/.agents/skills/seed/SKILL.md +38 -166
- package/.agents/skills/seed/references/animation.md +2 -2
- package/.agents/skills/seed/references/responsive.md +1 -1
- package/README.md +2 -2
- package/dist/catalog/components.js +4 -4
- package/dist/{chunk-7A2RXKGH.js → chunk-GJ557DGH.js} +1 -1
- package/dist/{chunk-7XLZCXUL.js → chunk-K4U67BVG.js} +1 -1
- package/dist/{chunk-TUJZMJXW.js → chunk-LK2L3C7D.js} +1 -1
- package/dist/{chunk-DSMGCFMJ.js → chunk-POFFOUQW.js} +2 -5
- package/dist/components/blocks/HeroBlock.js +2 -2
- package/dist/components/page-kits/LandingPageKit.js +3 -3
- package/dist/components/page-kits/ServiceSuitePageKit.js +3 -3
- package/dist/components/ui/AvatarUpload.js +1 -1
- package/dist/components/ui/MouseEffect.js +1 -1
- package/eslint-rules/nadicode/config.js +1 -0
- package/eslint-rules/nadicode/index.js +2 -0
- package/eslint-rules/nadicode/rules/__tests__/require-catalog-import.test.js +111 -0
- package/eslint-rules/nadicode/rules/no-has-svg-selector.js +1 -1
- package/eslint-rules/nadicode/rules/require-catalog-import.js +59 -0
- package/package.json +1 -338
- package/scripts/ds-check.mjs +0 -10
- package/scripts/sync-seed-skill.mjs +0 -3
- package/.agents/skills/seed/contract.md +0 -104
- package/.agents/skills/seed/intent-map.md +0 -320
- package/.agents/skills/seed/recipes/agency-home.md +0 -311
- package/.agents/skills/seed/recipes/agents-chat.md +0 -305
- package/.agents/skills/seed/recipes/analytics.md +0 -253
- package/.agents/skills/seed/recipes/auth.md +0 -254
- package/.agents/skills/seed/recipes/blog-content.md +0 -307
- package/.agents/skills/seed/recipes/checkout.md +0 -311
- package/.agents/skills/seed/recipes/company-about.md +0 -276
- package/.agents/skills/seed/recipes/company-contact.md +0 -234
- package/.agents/skills/seed/recipes/crud-form.md +0 -233
- package/.agents/skills/seed/recipes/crud-list-detail.md +0 -230
- package/.agents/skills/seed/recipes/dashboard.md +0 -354
- package/.agents/skills/seed/recipes/digital-workers.md +0 -314
- package/.agents/skills/seed/recipes/error-pages.md +0 -199
- package/.agents/skills/seed/recipes/marketing-landing.md +0 -293
- package/.agents/skills/seed/recipes/marketing-shell.md +0 -156
- package/.agents/skills/seed/recipes/navigation-shell.md +0 -786
- package/.agents/skills/seed/recipes/onboarding.md +0 -258
- package/.agents/skills/seed/recipes/pricing.md +0 -271
- package/.agents/skills/seed/recipes/service-detail.md +0 -302
- package/.agents/skills/seed/recipes/settings.md +0 -252
- package/.agents/skills/seed/references/blocks.md +0 -128
- package/.agents/skills/seed/references/components.md +0 -287
- package/.agents/skills/seed/references/icons.md +0 -169
- package/.agents/skills/seed/references/nextjs.md +0 -49
- package/.agents/skills/seed/references/tokens.md +0 -88
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
# Recipe: Blog / Content
|
|
2
|
-
|
|
3
|
-
Blog index, article pages, and changelog display with reading-optimized layout.
|
|
4
|
-
|
|
5
|
-
## Route Patterns
|
|
6
|
-
|
|
7
|
-
- `/blog` (index with post cards)
|
|
8
|
-
- `/blog/[slug]` (individual article)
|
|
9
|
-
- `/changelog` (version changelog)
|
|
10
|
-
|
|
11
|
-
## Shell
|
|
12
|
-
|
|
13
|
-
`marketing-shell` (HeaderBlock + FooterBlock)
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Layout Blueprint: Blog Index (Desktop)
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
+------------------------------------------------+
|
|
21
|
-
| HeaderBlock |
|
|
22
|
-
+------------------------------------------------+
|
|
23
|
-
| |
|
|
24
|
-
| Blog [Category filter] |
|
|
25
|
-
| Latest thoughts and updates |
|
|
26
|
-
| |
|
|
27
|
-
| +--------------------+ +-------------------+ |
|
|
28
|
-
| | Featured Post | | Post 2 | |
|
|
29
|
-
| | (large card) | | (standard card) | |
|
|
30
|
-
| | | +-------------------+ |
|
|
31
|
-
| | | | Post 3 | |
|
|
32
|
-
| | | | (standard card) | |
|
|
33
|
-
| +--------------------+ +-------------------+ |
|
|
34
|
-
| |
|
|
35
|
-
| +----------+ +----------+ +----------+ |
|
|
36
|
-
| | Post 4 | | Post 5 | | Post 6 | |
|
|
37
|
-
| +----------+ +----------+ +----------+ |
|
|
38
|
-
| |
|
|
39
|
-
| [Load More / Pagination] |
|
|
40
|
-
+------------------------------------------------+
|
|
41
|
-
| FooterBlock |
|
|
42
|
-
+------------------------------------------------+
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Layout Blueprint: Article Page (Desktop)
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
+------------------------------------------------+
|
|
49
|
-
| HeaderBlock |
|
|
50
|
-
+------------------------------------------------+
|
|
51
|
-
| |
|
|
52
|
-
| max-w-3xl centered |
|
|
53
|
-
| |
|
|
54
|
-
| Category Badge 5 min read |
|
|
55
|
-
| Article Title (h1) |
|
|
56
|
-
| Published Jan 1, 2025 by Author Name |
|
|
57
|
-
| |
|
|
58
|
-
| [Article hero image] |
|
|
59
|
-
| |
|
|
60
|
-
| Article body content with prose styling... |
|
|
61
|
-
| Headings, paragraphs, code blocks, |
|
|
62
|
-
| images, blockquotes... |
|
|
63
|
-
| |
|
|
64
|
-
| --- |
|
|
65
|
-
| Author card |
|
|
66
|
-
| Share buttons |
|
|
67
|
-
| |
|
|
68
|
-
| Related Posts (3 cards) |
|
|
69
|
-
| |
|
|
70
|
-
+------------------------------------------------+
|
|
71
|
-
| FooterBlock |
|
|
72
|
-
+------------------------------------------------+
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Section Sequence: Blog Index
|
|
78
|
-
|
|
79
|
-
### 1. Page Header
|
|
80
|
-
|
|
81
|
-
```tsx
|
|
82
|
-
<section className="py-12 md:py-16">
|
|
83
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
84
|
-
<div className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
|
|
85
|
-
<div>
|
|
86
|
-
<Heading level={1} size="display" >Blog</Heading>
|
|
87
|
-
<Typography variant="lead" className="text-text-secondary mt-2">
|
|
88
|
-
Latest thoughts and updates
|
|
89
|
-
</Typography>
|
|
90
|
-
</div>
|
|
91
|
-
<Select value={category} onValueChange={setCategory}>
|
|
92
|
-
<SelectTrigger className="w-48"><SelectValue placeholder="All categories" /></SelectTrigger>
|
|
93
|
-
<SelectContent>{/* Category options */}</SelectContent>
|
|
94
|
-
</Select>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
</section>
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 2. Featured + Recent Posts Grid
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
<section className="pb-16">
|
|
104
|
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
105
|
-
{/* Featured row */}
|
|
106
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
|
107
|
-
<Card className="glass-panel overflow-hidden lg:row-span-2">
|
|
108
|
-
{/* Featured post with large image */}
|
|
109
|
-
<img src={featured.image} alt="" className="w-full h-48 lg:h-64 object-cover" />
|
|
110
|
-
<div className="p-6">
|
|
111
|
-
<Badge variant="outline">{featured.category}</Badge>
|
|
112
|
-
<Heading level={3} size="subsection" className="mt-3">{featured.title}</Heading>
|
|
113
|
-
<Typography variant="p" className="text-text-secondary mt-2 line-clamp-3">
|
|
114
|
-
{featured.excerpt}
|
|
115
|
-
</Typography>
|
|
116
|
-
<div className="flex items-center gap-2 mt-4 text-text-tertiary text-sm">
|
|
117
|
-
<Avatar className="h-6 w-6"><AvatarImage src={featured.author.avatar} /></Avatar>
|
|
118
|
-
<span>{featured.author.name}</span>
|
|
119
|
-
<span>-</span>
|
|
120
|
-
<span>{featured.date}</span>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</Card>
|
|
124
|
-
<div className="space-y-6">
|
|
125
|
-
{recentPosts.slice(0, 2).map(post => (
|
|
126
|
-
<Card key={post.id} className="glass-panel p-6">
|
|
127
|
-
<Badge variant="outline">{post.category}</Badge>
|
|
128
|
-
<Heading level={4} size="title" className="mt-2">{post.title}</Heading>
|
|
129
|
-
<Typography variant="small" className="text-text-secondary mt-1 line-clamp-2">
|
|
130
|
-
{post.excerpt}
|
|
131
|
-
</Typography>
|
|
132
|
-
</Card>
|
|
133
|
-
))}
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
|
|
137
|
-
{/* Remaining posts grid */}
|
|
138
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
139
|
-
{remainingPosts.map(post => (
|
|
140
|
-
<Card key={post.id} className="glass-panel p-6">
|
|
141
|
-
<Badge variant="outline">{post.category}</Badge>
|
|
142
|
-
<Heading level={4} size="title" className="mt-2">{post.title}</Heading>
|
|
143
|
-
<Typography variant="small" className="text-text-secondary mt-1 line-clamp-2">
|
|
144
|
-
{post.excerpt}
|
|
145
|
-
</Typography>
|
|
146
|
-
</Card>
|
|
147
|
-
))}
|
|
148
|
-
</div>
|
|
149
|
-
|
|
150
|
-
{/* Pagination */}
|
|
151
|
-
<div className="mt-12 flex justify-center">
|
|
152
|
-
<Pagination current={page} total={totalPages} onPageChange={setPage} />
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
</section>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Article Page: Prose Content
|
|
159
|
-
|
|
160
|
-
```tsx
|
|
161
|
-
<article className="max-w-3xl mx-auto px-4 sm:px-6 py-12 md:py-16">
|
|
162
|
-
<header className="mb-8">
|
|
163
|
-
<div className="flex items-center gap-3 mb-4">
|
|
164
|
-
<Badge variant="outline">{post.category}</Badge>
|
|
165
|
-
<Typography variant="small" className="text-text-tertiary">
|
|
166
|
-
{post.readingTime} min read
|
|
167
|
-
</Typography>
|
|
168
|
-
</div>
|
|
169
|
-
<Heading level={1} size="display" >{post.title}</Heading>
|
|
170
|
-
<div className="flex items-center gap-3 mt-4 text-text-secondary">
|
|
171
|
-
<Avatar><AvatarImage src={post.author.avatar} /></Avatar>
|
|
172
|
-
<div>
|
|
173
|
-
<Typography variant="small" className="font-medium text-text-primary">
|
|
174
|
-
{post.author.name}
|
|
175
|
-
</Typography>
|
|
176
|
-
<Typography variant="small">{post.date}</Typography>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
</header>
|
|
180
|
-
|
|
181
|
-
{/* Prose content */}
|
|
182
|
-
<div className="prose prose-neutral dark:prose-invert max-w-none">
|
|
183
|
-
{post.content}
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
|
-
{/* Author card + share */}
|
|
187
|
-
<Separator className="my-12" />
|
|
188
|
-
<Card className="glass-panel p-6 flex items-center gap-4">
|
|
189
|
-
<Avatar className="h-12 w-12"><AvatarImage src={post.author.avatar} /></Avatar>
|
|
190
|
-
<div>
|
|
191
|
-
<Heading level={4} size="title" >{post.author.name}</Heading>
|
|
192
|
-
<Typography variant="small" className="text-text-secondary">{post.author.bio}</Typography>
|
|
193
|
-
</div>
|
|
194
|
-
</Card>
|
|
195
|
-
</article>
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## Animation Storyboard
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
ANIMATION STORYBOARD
|
|
204
|
-
====================
|
|
205
|
-
BUDGET: 600ms (index) / 300ms (article) | SPRING: snappy | REDUCED: opacity-only
|
|
206
|
-
|
|
207
|
-
BLOG INDEX:
|
|
208
|
-
T+0ms [nav] Header visible (instant)
|
|
209
|
-
T+50ms [header] Blog title + filter {fadeInUp, snappy}
|
|
210
|
-
T+130ms [featured] Featured post card {fadeInUp, snappy}
|
|
211
|
-
T+210ms [recent] Recent post cards stagger {blockStagger, 80ms}
|
|
212
|
-
T+450ms [grid] Remaining posts stagger {blockStagger, 80ms, max 6}
|
|
213
|
-
|
|
214
|
-
ARTICLE:
|
|
215
|
-
T+0ms [nav] Header visible (instant)
|
|
216
|
-
T+50ms [meta] Category + reading time {fadeIn, snappy}
|
|
217
|
-
T+100ms [title] Article title {fadeInUp, snappy}
|
|
218
|
-
T+200ms [content] Article body fades in {fadeIn, gentle}
|
|
219
|
-
|
|
220
|
-
REDUCED MOTION: All items visible immediately
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Required Components
|
|
226
|
-
|
|
227
|
-
| Component | Import Path | Purpose |
|
|
228
|
-
|-----------|-------------|---------|
|
|
229
|
-
| `Card` | `@vadimcomanescu/nadicode-design-system/card` | Post cards |
|
|
230
|
-
| `Badge` | `@vadimcomanescu/nadicode-design-system/badge` | Category tags |
|
|
231
|
-
| `Avatar` | `@vadimcomanescu/nadicode-design-system/avatar` | Author avatars |
|
|
232
|
-
| `Typography` | `@vadimcomanescu/nadicode-design-system/typography` | Headings, body |
|
|
233
|
-
| `Pagination` | `@vadimcomanescu/nadicode-design-system/pagination` | Blog index pages |
|
|
234
|
-
| `Separator` | `@vadimcomanescu/nadicode-design-system/separator` | Content dividers |
|
|
235
|
-
| `Select` | `@vadimcomanescu/nadicode-design-system/select` | Category filter |
|
|
236
|
-
| `HeaderBlock` | `@vadimcomanescu/nadicode-design-system/header-block` | Site navigation |
|
|
237
|
-
| `FooterBlock` | `@vadimcomanescu/nadicode-design-system/footer-block` | Site footer |
|
|
238
|
-
| `ScrollFadeIn` | `@vadimcomanescu/nadicode-design-system/scroll-fade-in` | Below-fold animations |
|
|
239
|
-
| `Button` | `@vadimcomanescu/nadicode-design-system/button` | Share, read more |
|
|
240
|
-
|
|
241
|
-
### Allowed (optional)
|
|
242
|
-
|
|
243
|
-
`ChangelogBlock`, `NewsletterBlock`, `Tabs`, `Input` (search), `Breadcrumb`, `Tooltip`, `CodeBlock`
|
|
244
|
-
|
|
245
|
-
### Forbidden
|
|
246
|
-
|
|
247
|
-
`Sidebar`, `DataTable`, `FormWizard`, chart components, agentic components
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## Required States
|
|
252
|
-
|
|
253
|
-
| State | Trigger | Visual |
|
|
254
|
-
|-------|---------|--------|
|
|
255
|
-
| `loading` | Fetching posts | Skeleton post cards |
|
|
256
|
-
| `empty` | No posts (unlikely for blog) | `Empty` with "No posts yet" |
|
|
257
|
-
| `has-data` | Posts loaded | Full grid layout |
|
|
258
|
-
| `category-filtered` | Category selected | Filtered post grid |
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Responsive Contract
|
|
263
|
-
|
|
264
|
-
| Breakpoint | Blog Index Grid | Article Width |
|
|
265
|
-
|------------|----------------|---------------|
|
|
266
|
-
| Mobile | 1 col | Full width, px-4 |
|
|
267
|
-
| `sm:` | 2 col | max-w-3xl, px-6 |
|
|
268
|
-
| `lg:` | Featured 2-col + 3-col grid | max-w-3xl, px-6 |
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## Styling Rules
|
|
273
|
-
|
|
274
|
-
- Post cards: `glass-panel` with overflow-hidden for images
|
|
275
|
-
- Article prose: Tailwind typography plugin (`prose prose-neutral dark:prose-invert`)
|
|
276
|
-
- Reading width: `max-w-3xl` (768px) for article content
|
|
277
|
-
- Category badges: `variant="outline"`
|
|
278
|
-
- No raw palette colors
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## Accessibility
|
|
283
|
-
|
|
284
|
-
- Blog index is a `<main>` with article cards as `<article>` elements
|
|
285
|
-
- Article page uses semantic `<article>`, `<header>`, heading hierarchy
|
|
286
|
-
- Images have alt text
|
|
287
|
-
- Pagination uses `<nav>` with `aria-label="Blog pagination"`
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## Reference Implementations
|
|
292
|
-
|
|
293
|
-
- `src/app/blog/page.tsx`
|
|
294
|
-
- `src/app/changelog/page.tsx`
|
|
295
|
-
- `src/components/blocks/ChangelogBlock.tsx`
|
|
296
|
-
- `src/components/blocks/NewsletterBlock.tsx`
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## Verification
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
npx tsc --noEmit
|
|
304
|
-
npm run lint
|
|
305
|
-
npm run test
|
|
306
|
-
npx vitest run src/test/css-variable-usage.test.ts
|
|
307
|
-
```
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
# Recipe: Checkout
|
|
2
|
-
|
|
3
|
-
Payment flow with Stripe integration, order summary, and success state.
|
|
4
|
-
|
|
5
|
-
## Route Patterns
|
|
6
|
-
|
|
7
|
-
- `/checkout`
|
|
8
|
-
- `/checkout/success`
|
|
9
|
-
|
|
10
|
-
## Shell
|
|
11
|
-
|
|
12
|
-
`marketing-shell` (minimal: logo + trust badge, no full nav to avoid abandonment)
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Layout Blueprint (Desktop)
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
+------------------------------------------------+
|
|
20
|
-
| Logo Secure checkout [Back to cart]|
|
|
21
|
-
+------------------------------------------------+
|
|
22
|
-
| |
|
|
23
|
-
| +-------------------------+ +-------------+ |
|
|
24
|
-
| | Checkout Form | | Order | |
|
|
25
|
-
| | | | Summary | |
|
|
26
|
-
| | Contact Information | | | |
|
|
27
|
-
| | [Email input] | | Item 1 $29 | |
|
|
28
|
-
| | | | Item 2 $49 | |
|
|
29
|
-
| | Payment | | | |
|
|
30
|
-
| | [Stripe Card Element] | | Subtotal $78| |
|
|
31
|
-
| | | | Tax $8 | |
|
|
32
|
-
| | Billing Address | | ----------- | |
|
|
33
|
-
| | [Address fields] | | Total $86| |
|
|
34
|
-
| | | | | |
|
|
35
|
-
| | [Pay $86.00] | | [Coupon] | |
|
|
36
|
-
| +-------------------------+ +-------------+ |
|
|
37
|
-
| |
|
|
38
|
-
| [Stripe] [SSL] [Money-back guarantee badges] |
|
|
39
|
-
+------------------------------------------------+
|
|
40
|
-
|
|
41
|
-
Success Page:
|
|
42
|
-
+------------------------------------------------+
|
|
43
|
-
| Logo [Home] |
|
|
44
|
-
+------------------------------------------------+
|
|
45
|
-
| |
|
|
46
|
-
| [ConfettiBurst] |
|
|
47
|
-
| [SuccessCheck] |
|
|
48
|
-
| |
|
|
49
|
-
| Payment successful! |
|
|
50
|
-
| Order #12345 confirmed. |
|
|
51
|
-
| |
|
|
52
|
-
| We've sent a confirmation to your email. |
|
|
53
|
-
| |
|
|
54
|
-
| [Go to Dashboard] [View Receipt] |
|
|
55
|
-
| |
|
|
56
|
-
+------------------------------------------------+
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Section Sequence
|
|
62
|
-
|
|
63
|
-
### 1. Minimal Header
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
<header className="flex items-center justify-between px-6 py-4 border-b border-border">
|
|
67
|
-
<Logo className="h-6" />
|
|
68
|
-
<div className="flex items-center gap-2 text-text-secondary">
|
|
69
|
-
<LockIcon size={14} />
|
|
70
|
-
<Typography variant="small">Secure checkout</Typography>
|
|
71
|
-
</div>
|
|
72
|
-
<Button variant="ghost" size="sm" asChild>
|
|
73
|
-
<a href="/pricing">Back</a>
|
|
74
|
-
</Button>
|
|
75
|
-
</header>
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### 2. Checkout Form + Order Summary (2-column)
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8 md:py-12">
|
|
82
|
-
<div className="grid grid-cols-1 lg:grid-cols-[1fr_380px] gap-8">
|
|
83
|
-
{/* Left: Form */}
|
|
84
|
-
<div className="space-y-6">
|
|
85
|
-
{/* Contact */}
|
|
86
|
-
<Card className="glass-panel p-6">
|
|
87
|
-
<Heading level={4} size="title" className="mb-4">Contact information</Heading>
|
|
88
|
-
<div className="space-y-4">
|
|
89
|
-
<FormField>
|
|
90
|
-
<FormLabel>Email</FormLabel>
|
|
91
|
-
<FormControl><Input type="email" /></FormControl>
|
|
92
|
-
</FormField>
|
|
93
|
-
</div>
|
|
94
|
-
</Card>
|
|
95
|
-
|
|
96
|
-
{/* Payment */}
|
|
97
|
-
<Card className="glass-panel p-6">
|
|
98
|
-
<Heading level={4} size="title" className="mb-4">Payment</Heading>
|
|
99
|
-
<CheckoutForm
|
|
100
|
-
amount={totalAmount}
|
|
101
|
-
onSuccess={handlePaymentSuccess}
|
|
102
|
-
onError={handlePaymentError}
|
|
103
|
-
/>
|
|
104
|
-
</Card>
|
|
105
|
-
|
|
106
|
-
{/* Billing Address */}
|
|
107
|
-
<Card className="glass-panel p-6">
|
|
108
|
-
<Heading level={4} size="title" className="mb-4">Billing address</Heading>
|
|
109
|
-
<div className="grid grid-cols-2 gap-4">
|
|
110
|
-
<FormField>
|
|
111
|
-
<FormLabel>First name</FormLabel>
|
|
112
|
-
<FormControl><Input /></FormControl>
|
|
113
|
-
</FormField>
|
|
114
|
-
<FormField>
|
|
115
|
-
<FormLabel>Last name</FormLabel>
|
|
116
|
-
<FormControl><Input /></FormControl>
|
|
117
|
-
</FormField>
|
|
118
|
-
<FormField className="col-span-2">
|
|
119
|
-
<FormLabel>Address</FormLabel>
|
|
120
|
-
<FormControl><Input /></FormControl>
|
|
121
|
-
</FormField>
|
|
122
|
-
{/* City, State, ZIP */}
|
|
123
|
-
</div>
|
|
124
|
-
</Card>
|
|
125
|
-
</div>
|
|
126
|
-
|
|
127
|
-
{/* Right: Order Summary */}
|
|
128
|
-
<div className="lg:sticky lg:top-8 self-start">
|
|
129
|
-
<Card className="glass-panel p-6">
|
|
130
|
-
<Heading level={4} size="title" className="mb-4">Order summary</Heading>
|
|
131
|
-
<div className="space-y-3">
|
|
132
|
-
{items.map(item => (
|
|
133
|
-
<div key={item.id} className="flex items-center justify-between">
|
|
134
|
-
<Typography variant="small">{item.name}</Typography>
|
|
135
|
-
<Typography variant="small" className="font-medium">${item.price}</Typography>
|
|
136
|
-
</div>
|
|
137
|
-
))}
|
|
138
|
-
</div>
|
|
139
|
-
<Separator className="my-4" />
|
|
140
|
-
<div className="space-y-2">
|
|
141
|
-
<div className="flex justify-between text-text-secondary text-sm">
|
|
142
|
-
<span>Subtotal</span><span>${subtotal}</span>
|
|
143
|
-
</div>
|
|
144
|
-
<div className="flex justify-between text-text-secondary text-sm">
|
|
145
|
-
<span>Tax</span><span>${tax}</span>
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
<Separator className="my-4" />
|
|
149
|
-
<div className="flex justify-between font-bold text-lg">
|
|
150
|
-
<span>Total</span><span>${total}</span>
|
|
151
|
-
</div>
|
|
152
|
-
|
|
153
|
-
{/* Coupon input */}
|
|
154
|
-
<div className="mt-4">
|
|
155
|
-
<InputGroup>
|
|
156
|
-
<Input placeholder="Coupon code" />
|
|
157
|
-
<Button variant="outline">Apply</Button>
|
|
158
|
-
</InputGroup>
|
|
159
|
-
</div>
|
|
160
|
-
</Card>
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
{/* Trust badges */}
|
|
165
|
-
<div className="flex items-center justify-center gap-6 mt-8 text-text-tertiary">
|
|
166
|
-
<div className="flex items-center gap-1 text-sm">
|
|
167
|
-
<ShieldIcon size={14} /> SSL Encrypted
|
|
168
|
-
</div>
|
|
169
|
-
<div className="flex items-center gap-1 text-sm">
|
|
170
|
-
<RefreshIcon size={14} /> 30-day guarantee
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### 3. Success Page
|
|
177
|
-
|
|
178
|
-
```tsx
|
|
179
|
-
<div className="min-h-dvh flex flex-col items-center justify-center p-6 text-center">
|
|
180
|
-
<ConfettiBurst trigger={showCelebration} />
|
|
181
|
-
<SuccessCheck className="mb-6" />
|
|
182
|
-
<Heading level={2} size="section" >Payment successful!</Heading>
|
|
183
|
-
<Typography variant="p" className="text-text-secondary mt-2 mb-2">
|
|
184
|
-
Order #{orderId} confirmed.
|
|
185
|
-
</Typography>
|
|
186
|
-
<Typography variant="small" className="text-text-tertiary mb-8">
|
|
187
|
-
We've sent a confirmation to {email}
|
|
188
|
-
</Typography>
|
|
189
|
-
<div className="flex gap-4">
|
|
190
|
-
<Button asChild><a href="/dashboard">Go to Dashboard</a></Button>
|
|
191
|
-
<Button variant="outline" asChild><a href={receiptUrl}>View Receipt</a></Button>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Animation Storyboard
|
|
199
|
-
|
|
200
|
-
```
|
|
201
|
-
ANIMATION STORYBOARD
|
|
202
|
-
====================
|
|
203
|
-
|
|
204
|
-
CHECKOUT PAGE:
|
|
205
|
-
BUDGET: 400ms | SPRING: snappy | REDUCED: opacity-only
|
|
206
|
-
|
|
207
|
-
T+0ms [header] Minimal header visible (instant)
|
|
208
|
-
T+50ms [contact] Contact section {fadeInUp, snappy}
|
|
209
|
-
T+150ms [payment] Payment section {fadeInUp, snappy}
|
|
210
|
-
T+250ms [address] Billing address section {fadeInUp, snappy}
|
|
211
|
-
T+100ms [summary] Order summary (right column) {fadeIn, snappy}
|
|
212
|
-
|
|
213
|
-
SUCCESS PAGE:
|
|
214
|
-
BUDGET: 500ms | SPRING: bouncy | REDUCED: check visible, no confetti
|
|
215
|
-
|
|
216
|
-
T+0ms [confetti] ConfettiBurst fires (particle animation)
|
|
217
|
-
T+100ms [check] SuccessCheck animates {scaleIn, bouncy}
|
|
218
|
-
T+300ms [title] Success title fades in {fadeInUp, gentle}
|
|
219
|
-
T+400ms [details] Order details fade in {fadeIn, snappy}
|
|
220
|
-
T+500ms [actions] Buttons fade in {fadeIn, snappy}
|
|
221
|
-
|
|
222
|
-
REDUCED MOTION: All items visible immediately, no confetti
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## Required Components
|
|
228
|
-
|
|
229
|
-
| Component | Import Path | Purpose |
|
|
230
|
-
|-----------|-------------|---------|
|
|
231
|
-
| `CheckoutForm` | `@vadimcomanescu/nadicode-design-system/checkout-form` | Stripe Elements payment |
|
|
232
|
-
| `Card` | `@vadimcomanescu/nadicode-design-system/card` | Section containers, order summary |
|
|
233
|
-
| `Input` | `@vadimcomanescu/nadicode-design-system/input` | Contact, address fields |
|
|
234
|
-
| `InputGroup` | `@vadimcomanescu/nadicode-design-system/input-group` | Coupon input + apply button |
|
|
235
|
-
| `Button` | `@vadimcomanescu/nadicode-design-system/button` | Submit, apply, navigation |
|
|
236
|
-
| `Typography` | `@vadimcomanescu/nadicode-design-system/typography` | Headings, text |
|
|
237
|
-
| `Separator` | `@vadimcomanescu/nadicode-design-system/separator` | Price dividers |
|
|
238
|
-
| `Logo` | `@vadimcomanescu/nadicode-design-system/logo` | Brand mark |
|
|
239
|
-
| `Form` / `FormField` | `@vadimcomanescu/nadicode-design-system/form` | Form management |
|
|
240
|
-
| `ConfettiBurst` | `@vadimcomanescu/nadicode-design-system/confetti-burst` | Success celebration |
|
|
241
|
-
| `SuccessCheck` | `@vadimcomanescu/nadicode-design-system/success-check` | Success checkmark |
|
|
242
|
-
| `Alert` | `@vadimcomanescu/nadicode-design-system/alert` | Payment errors |
|
|
243
|
-
| `Spinner` | `@vadimcomanescu/nadicode-design-system/spinner` | Processing state |
|
|
244
|
-
|
|
245
|
-
### Allowed (optional)
|
|
246
|
-
|
|
247
|
-
`CheckoutFormDemo`, `Label`, `Select` (country picker), `NativeSelect`, `Badge`, `Tooltip`
|
|
248
|
-
|
|
249
|
-
### Forbidden
|
|
250
|
-
|
|
251
|
-
`Sidebar`, `NavigationMenu`, `DataTable`, chart components, agentic components, decorative effects, marketing blocks
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## Required States
|
|
256
|
-
|
|
257
|
-
| State | Trigger | Visual |
|
|
258
|
-
|-------|---------|--------|
|
|
259
|
-
| `default` | Page loaded | Form ready for input |
|
|
260
|
-
| `submitting` | Pay button clicked | Button shows Spinner, form disabled |
|
|
261
|
-
| `processing` | Stripe processing | "Processing payment..." message |
|
|
262
|
-
| `error` | Payment failed | `Alert` variant="destructive" with error + retry |
|
|
263
|
-
| `success` | Payment succeeded | Redirect to success page with celebration |
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
## Responsive Contract
|
|
268
|
-
|
|
269
|
-
| Breakpoint | Layout | Order Summary |
|
|
270
|
-
|------------|--------|---------------|
|
|
271
|
-
| Mobile | Single column, summary above form | Collapsible or stacked above form |
|
|
272
|
-
| `lg:` | 2-column: form (flex-1) + summary (380px sticky) | Sticky sidebar |
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## Styling Rules
|
|
277
|
-
|
|
278
|
-
- Form sections: `glass-panel p-6`
|
|
279
|
-
- Order summary: `glass-panel p-6`, sticky on desktop
|
|
280
|
-
- Trust badges: `text-text-tertiary`, small, centered
|
|
281
|
-
- No heavy decoration (reduce friction)
|
|
282
|
-
- Minimal navigation (prevent abandonment)
|
|
283
|
-
- Labels always stacked above inputs
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
## Accessibility
|
|
288
|
-
|
|
289
|
-
- Payment form has proper labels (Stripe Elements handle internal a11y)
|
|
290
|
-
- Error messages use `role="alert"`
|
|
291
|
-
- Form fields have `autocomplete` attributes (email, name, address)
|
|
292
|
-
- Tab order: contact -> payment -> address -> submit
|
|
293
|
-
- Success page auto-announces via `aria-live`
|
|
294
|
-
|
|
295
|
-
---
|
|
296
|
-
|
|
297
|
-
## Reference Implementations
|
|
298
|
-
|
|
299
|
-
- `src/components/ui/CheckoutForm.tsx`
|
|
300
|
-
- `src/components/ui/CheckoutFormDemo.tsx`
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
## Verification
|
|
305
|
-
|
|
306
|
-
```bash
|
|
307
|
-
npx tsc --noEmit
|
|
308
|
-
npm run lint
|
|
309
|
-
npm run test
|
|
310
|
-
npx vitest run src/test/css-variable-usage.test.ts
|
|
311
|
-
```
|