@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,253 +0,0 @@
|
|
|
1
|
-
# Recipe: Analytics
|
|
2
|
-
|
|
3
|
-
Trend analysis page with date filters, KPI summary, chart grid, and data breakdowns.
|
|
4
|
-
|
|
5
|
-
## Route Pattern
|
|
6
|
-
|
|
7
|
-
`/analytics`
|
|
8
|
-
|
|
9
|
-
## Shell
|
|
10
|
-
|
|
11
|
-
`app-shell` (Sidebar + top bar + SearchCommand)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Layout Blueprint (Desktop)
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
+--+---------------------------------------------+
|
|
19
|
-
| | Breadcrumb: Home > Analytics |
|
|
20
|
-
|S | Analytics [DateRange] [Export] [Tab] |
|
|
21
|
-
|I | |
|
|
22
|
-
|D | +--------+ +--------+ +--------+ +--------+ |
|
|
23
|
-
|E | | KPI 1 | | KPI 2 | | KPI 3 | | KPI 4 | |
|
|
24
|
-
|B | +--------+ +--------+ +--------+ +--------+ |
|
|
25
|
-
|A | |
|
|
26
|
-
|R | +------------------------------------------+ |
|
|
27
|
-
| | | Primary Chart (AreaChart, full width) | |
|
|
28
|
-
| | | | |
|
|
29
|
-
| | +------------------------------------------+ |
|
|
30
|
-
| | |
|
|
31
|
-
| | +-------------------+ +--------------------+ |
|
|
32
|
-
| | | Breakdown Chart | | Distribution Chart | |
|
|
33
|
-
| | | (BarChart) | | (PieChart) | |
|
|
34
|
-
| | +-------------------+ +--------------------+ |
|
|
35
|
-
| | |
|
|
36
|
-
| | +------------------------------------------+ |
|
|
37
|
-
| | | Data Table (detailed breakdown) | |
|
|
38
|
-
| | +------------------------------------------+ |
|
|
39
|
-
+--+---------------------------------------------+
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Section Sequence
|
|
45
|
-
|
|
46
|
-
### 1. Page Header + Controls
|
|
47
|
-
|
|
48
|
-
```tsx
|
|
49
|
-
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
50
|
-
<div>
|
|
51
|
-
<Breadcrumb>...</Breadcrumb>
|
|
52
|
-
<Heading level={2} size="section" >Analytics</Heading>
|
|
53
|
-
</div>
|
|
54
|
-
<div className="flex items-center gap-3">
|
|
55
|
-
<DateRangePicker value={dateRange} onChange={setDateRange} />
|
|
56
|
-
<Button variant="outline"><DownloadIcon size={16} /> Export</Button>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 2. View Tabs (optional)
|
|
62
|
-
|
|
63
|
-
```tsx
|
|
64
|
-
<Tabs value={view} onValueChange={setView} className="mt-4">
|
|
65
|
-
<TabsList>
|
|
66
|
-
<TabsTrigger value="overview">Overview</TabsTrigger>
|
|
67
|
-
<TabsTrigger value="engagement">Engagement</TabsTrigger>
|
|
68
|
-
<TabsTrigger value="revenue">Revenue</TabsTrigger>
|
|
69
|
-
</TabsList>
|
|
70
|
-
</Tabs>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### 3. KPI Summary Row
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mt-6">
|
|
77
|
-
{kpis.map(kpi => (
|
|
78
|
-
<Card key={kpi.id} className="glass-panel p-6">
|
|
79
|
-
<Typography variant="small" className="text-text-secondary">{kpi.label}</Typography>
|
|
80
|
-
<div className="flex items-baseline gap-2 mt-1">
|
|
81
|
-
<CountingNumber value={kpi.value} className="text-2xl font-bold" />
|
|
82
|
-
<Badge variant={kpi.trend > 0 ? "success" : "destructive"}>
|
|
83
|
-
{kpi.trend > 0 ? "+" : ""}{kpi.trend}%
|
|
84
|
-
</Badge>
|
|
85
|
-
</div>
|
|
86
|
-
<Typography variant="small" className="text-text-tertiary mt-1">
|
|
87
|
-
vs. previous period
|
|
88
|
-
</Typography>
|
|
89
|
-
</Card>
|
|
90
|
-
))}
|
|
91
|
-
</div>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 4. Primary Chart (full width)
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
<Card className="glass-panel p-6 mt-6">
|
|
98
|
-
<div className="flex items-center justify-between mb-4">
|
|
99
|
-
<Heading level={4} size="title" >Trend Over Time</Heading>
|
|
100
|
-
<Select value={metric} onValueChange={setMetric}>
|
|
101
|
-
<SelectTrigger className="w-40"><SelectValue /></SelectTrigger>
|
|
102
|
-
<SelectContent>
|
|
103
|
-
<SelectItem value="visitors">Visitors</SelectItem>
|
|
104
|
-
<SelectItem value="revenue">Revenue</SelectItem>
|
|
105
|
-
</SelectContent>
|
|
106
|
-
</Select>
|
|
107
|
-
</div>
|
|
108
|
-
<AreaChart data={trendData} height={300} />
|
|
109
|
-
</Card>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 5. Secondary Charts (2 column)
|
|
113
|
-
|
|
114
|
-
```tsx
|
|
115
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 lg:gap-6 mt-6">
|
|
116
|
-
<Card className="glass-panel p-6">
|
|
117
|
-
<Heading level={4} size="title" className="mb-4">By Category</Heading>
|
|
118
|
-
<BarChart data={breakdownData} />
|
|
119
|
-
</Card>
|
|
120
|
-
<Card className="glass-panel p-6">
|
|
121
|
-
<Heading level={4} size="title" className="mb-4">Distribution</Heading>
|
|
122
|
-
<PieChart data={distributionData} />
|
|
123
|
-
</Card>
|
|
124
|
-
</div>
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### 6. Detailed Breakdown Table (optional)
|
|
128
|
-
|
|
129
|
-
```tsx
|
|
130
|
-
<Card className="glass-panel mt-6">
|
|
131
|
-
<div className="flex items-center justify-between p-6 pb-0">
|
|
132
|
-
<Heading level={4} size="title" >Detailed Breakdown</Heading>
|
|
133
|
-
<Input placeholder="Search..." className="w-48" />
|
|
134
|
-
</div>
|
|
135
|
-
<DataTable columns={breakdownColumns} data={breakdownRows} />
|
|
136
|
-
</Card>
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Animation Storyboard
|
|
142
|
-
|
|
143
|
-
```
|
|
144
|
-
ANIMATION STORYBOARD
|
|
145
|
-
====================
|
|
146
|
-
BUDGET: 550ms | SPRING: snappy | REDUCED: opacity-only
|
|
147
|
-
|
|
148
|
-
T+0ms [shell] Sidebar + top bar visible (instant)
|
|
149
|
-
T+50ms [header] Title + date filter {fadeInUp, snappy}
|
|
150
|
-
T+100ms [tabs] View tabs {fadeIn, snappy}
|
|
151
|
-
T+150ms [kpi-1..4] KPI cards stagger {blockStagger, 80ms apart}
|
|
152
|
-
T+470ms [chart-1] Primary chart fades in {fadeIn, gentle}
|
|
153
|
-
T+550ms [chart-2] Secondary charts fade in {fadeIn, gentle}
|
|
154
|
-
|
|
155
|
-
SCROLL-TRIGGERED:
|
|
156
|
-
[table] DataTable ScrollFadeIn at 20% {fadeIn, snappy}
|
|
157
|
-
|
|
158
|
-
DATE FILTER CHANGE:
|
|
159
|
-
[kpis] CountingNumber animate to new values
|
|
160
|
-
[charts] Chart data transitions smoothly (recharts built-in)
|
|
161
|
-
|
|
162
|
-
REDUCED MOTION: All items visible immediately
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## Required Components
|
|
168
|
-
|
|
169
|
-
| Component | Import Path | Purpose |
|
|
170
|
-
|-----------|-------------|---------|
|
|
171
|
-
| `Card` | `@vadimcomanescu/nadicode-design-system/card` | KPI cards, chart containers |
|
|
172
|
-
| `Badge` | `@vadimcomanescu/nadicode-design-system/badge` | Trend indicators |
|
|
173
|
-
| `Typography` | `@vadimcomanescu/nadicode-design-system/typography` | Titles, labels |
|
|
174
|
-
| `Breadcrumb` | `@vadimcomanescu/nadicode-design-system/breadcrumb` | Navigation |
|
|
175
|
-
| `Button` | `@vadimcomanescu/nadicode-design-system/button` | Export, actions |
|
|
176
|
-
| `DateRangePicker` | `@vadimcomanescu/nadicode-design-system/date-range-picker` | Date filter |
|
|
177
|
-
| `Tabs` | `@vadimcomanescu/nadicode-design-system/tabs` | View switching |
|
|
178
|
-
| `Select` | `@vadimcomanescu/nadicode-design-system/select` | Metric selector |
|
|
179
|
-
| `AreaChart` | `@vadimcomanescu/nadicode-design-system/charts/area-chart` | Primary trend |
|
|
180
|
-
| `BarChart` | `@vadimcomanescu/nadicode-design-system/charts/bar-chart` | Category breakdown |
|
|
181
|
-
| `PieChart` | `@vadimcomanescu/nadicode-design-system/charts/pie-chart` | Distribution |
|
|
182
|
-
| `CountingNumber` | `@vadimcomanescu/nadicode-design-system/text-effects/counting-number` | Animated KPIs |
|
|
183
|
-
| `Skeleton` | `@vadimcomanescu/nadicode-design-system/skeleton` | Loading state |
|
|
184
|
-
| `Empty` | `@vadimcomanescu/nadicode-design-system/empty` | No-data state |
|
|
185
|
-
|
|
186
|
-
### Allowed (optional)
|
|
187
|
-
|
|
188
|
-
`LineChart`, `RadarChart`, `RadialBarChart`, `HeatmapChart`, `DataTable`, `Tooltip`, `Progress`
|
|
189
|
-
|
|
190
|
-
### Forbidden
|
|
191
|
-
|
|
192
|
-
`HeroBlock`, `FormWizard`, `AuthLayout`, decorative effects, agentic components
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Required States
|
|
197
|
-
|
|
198
|
-
| State | Trigger | Visual |
|
|
199
|
-
|-------|---------|--------|
|
|
200
|
-
| `loading` | Initial data fetch or filter change | Skeleton KPIs + skeleton chart areas |
|
|
201
|
-
| `empty` | No data for selected range | `Empty` with chart icon, "No data for this period" |
|
|
202
|
-
| `has-data` | Data loaded | Full charts and KPIs |
|
|
203
|
-
| `error` | API failure | `Alert` variant="destructive" with retry |
|
|
204
|
-
| `date-filtered` | User changes date range | KPIs animate, charts re-render with new data |
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Responsive Contract
|
|
209
|
-
|
|
210
|
-
| Breakpoint | KPIs | Charts | Table |
|
|
211
|
-
|------------|------|--------|-------|
|
|
212
|
-
| Mobile | 1 col | 1 col, stacked | Horizontal scroll |
|
|
213
|
-
| `sm:` | 2 col | 1 col | Horizontal scroll |
|
|
214
|
-
| `lg:` | 4 col | Primary full, secondary 2-col | Full table |
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Styling Rules
|
|
219
|
-
|
|
220
|
-
- Chart containers: `glass-panel p-6`
|
|
221
|
-
- Chart colors: only `chart-1` through `chart-6` tokens
|
|
222
|
-
- KPI cards: `glass-panel p-6`
|
|
223
|
-
- No raw palette colors
|
|
224
|
-
- Grid gaps: `gap-4 lg:gap-6`
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## Accessibility
|
|
229
|
-
|
|
230
|
-
- Charts use `ChartContainer` with `aria-label`
|
|
231
|
-
- Date range picker is keyboard accessible
|
|
232
|
-
- KPI trend badges include direction in text ("up 12%")
|
|
233
|
-
- Tab navigation is keyboard-navigable
|
|
234
|
-
- Export button has `aria-label="Export analytics data"`
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
## Reference Implementations
|
|
239
|
-
|
|
240
|
-
- `src/components/blocks/ChartCollectionBlock.tsx`
|
|
241
|
-
- `src/components/blocks/StatsBlock.tsx`
|
|
242
|
-
- `src/components/blocks/InteractiveAreaChartBlock.tsx`
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## Verification
|
|
247
|
-
|
|
248
|
-
```bash
|
|
249
|
-
npx tsc --noEmit
|
|
250
|
-
npm run lint
|
|
251
|
-
npm run test
|
|
252
|
-
npx vitest run src/test/css-variable-usage.test.ts
|
|
253
|
-
```
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
# Recipe: Auth
|
|
2
|
-
|
|
3
|
-
Login, signup, password reset, and 2FA flows with split-screen or centered layout.
|
|
4
|
-
|
|
5
|
-
## Route Patterns
|
|
6
|
-
|
|
7
|
-
- `/login`
|
|
8
|
-
- `/signup`
|
|
9
|
-
- `/reset-password`
|
|
10
|
-
- `/verify` (2FA challenge)
|
|
11
|
-
|
|
12
|
-
## Shell
|
|
13
|
-
|
|
14
|
-
`auth-shell` (AuthLayout: split-screen or centered, minimal chrome)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Layout Blueprint (Desktop)
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
+------------------------------------------------+
|
|
22
|
-
| |
|
|
23
|
-
| +--------------------+ +-------------------+ |
|
|
24
|
-
| | | | | |
|
|
25
|
-
| | Brand Panel | | Auth Card | |
|
|
26
|
-
| | (illustration, | | (glass-floating) | |
|
|
27
|
-
| | testimonial, | | | |
|
|
28
|
-
| | or shader bg) | | Logo | |
|
|
29
|
-
| | | | Title | |
|
|
30
|
-
| | | | Subtitle | |
|
|
31
|
-
| | | | | |
|
|
32
|
-
| | | | [Email input] | |
|
|
33
|
-
| | | | [Password input] | |
|
|
34
|
-
| | | | | |
|
|
35
|
-
| | | | [Sign In] | |
|
|
36
|
-
| | | | Or continue with | |
|
|
37
|
-
| | | | [Google] [GitHub] | |
|
|
38
|
-
| | | | | |
|
|
39
|
-
| | | | Forgot password? | |
|
|
40
|
-
| | | | Don't have acct? | |
|
|
41
|
-
| +--------------------+ +-------------------+ |
|
|
42
|
-
| |
|
|
43
|
-
+------------------------------------------------+
|
|
44
|
-
|
|
45
|
-
Mobile: Brand panel hidden, auth card full-width centered
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Section Sequence
|
|
51
|
-
|
|
52
|
-
### 1. Auth Layout Wrapper
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
<AuthLayout>
|
|
56
|
-
{/* AuthLayout provides split-screen on desktop, centered on mobile */}
|
|
57
|
-
<LoginBlock
|
|
58
|
-
type="login"
|
|
59
|
-
variant="glass-panel"
|
|
60
|
-
showSocial
|
|
61
|
-
title="Welcome back"
|
|
62
|
-
description="Sign in to your account"
|
|
63
|
-
onLogin={handleLogin}
|
|
64
|
-
forgotPasswordHref="/reset-password"
|
|
65
|
-
signUpHref="/signup"
|
|
66
|
-
/>
|
|
67
|
-
</AuthLayout>
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Login Form (within LoginBlock or custom)
|
|
71
|
-
|
|
72
|
-
```tsx
|
|
73
|
-
<Card className="glass-floating p-8 w-full max-w-md">
|
|
74
|
-
<div className="flex flex-col items-center mb-6">
|
|
75
|
-
<Logo className="h-8 mb-4" />
|
|
76
|
-
<Heading level={3} size="subsection" >Welcome back</Heading>
|
|
77
|
-
<Typography variant="small" className="text-text-secondary mt-1">
|
|
78
|
-
Sign in to your account
|
|
79
|
-
</Typography>
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
{error && <Alert variant="destructive" className="mb-4">{error}</Alert>}
|
|
83
|
-
|
|
84
|
-
<form onSubmit={handleSubmit} className="space-y-4">
|
|
85
|
-
<div>
|
|
86
|
-
<Label htmlFor="email">Email</Label>
|
|
87
|
-
<Input id="email" type="email" placeholder="name@example.com" />
|
|
88
|
-
</div>
|
|
89
|
-
<div>
|
|
90
|
-
<Label htmlFor="password">Password</Label>
|
|
91
|
-
<PasswordInput id="password" />
|
|
92
|
-
</div>
|
|
93
|
-
<Button type="submit" className="w-full" disabled={isSubmitting}>
|
|
94
|
-
{isSubmitting ? <Spinner className="mr-2" /> : null}
|
|
95
|
-
Sign In
|
|
96
|
-
</Button>
|
|
97
|
-
</form>
|
|
98
|
-
|
|
99
|
-
<div className="relative my-6">
|
|
100
|
-
<Separator />
|
|
101
|
-
<span className="absolute left-1/2 -translate-x-1/2 -translate-y-1/2 bg-surface px-2 text-text-tertiary text-sm">
|
|
102
|
-
Or continue with
|
|
103
|
-
</span>
|
|
104
|
-
</div>
|
|
105
|
-
|
|
106
|
-
<div className="grid grid-cols-2 gap-3">
|
|
107
|
-
<Button variant="outline"><BrandIcons.Google className="mr-2 h-4 w-4" /> Google</Button>
|
|
108
|
-
<Button variant="outline"><BrandIcons.GitHub className="mr-2 h-4 w-4" /> GitHub</Button>
|
|
109
|
-
</div>
|
|
110
|
-
|
|
111
|
-
<div className="mt-6 text-center space-y-2">
|
|
112
|
-
<a href="/reset-password" className="text-sm text-link">Forgot password?</a>
|
|
113
|
-
<p className="text-sm text-text-secondary">
|
|
114
|
-
Don't have an account? <a href="/signup" className="text-link">Sign up</a>
|
|
115
|
-
</p>
|
|
116
|
-
</div>
|
|
117
|
-
</Card>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### 3. 2FA Challenge (separate route)
|
|
121
|
-
|
|
122
|
-
```tsx
|
|
123
|
-
<Card className="glass-floating p-8 w-full max-w-md text-center">
|
|
124
|
-
<Heading level={3} size="subsection" >Two-factor authentication</Heading>
|
|
125
|
-
<Typography variant="small" className="text-text-secondary mt-2 mb-6">
|
|
126
|
-
Enter the 6-digit code from your authenticator app
|
|
127
|
-
</Typography>
|
|
128
|
-
<InputOTP maxLength={6} onComplete={handleVerify}>
|
|
129
|
-
<InputOTPGroup>
|
|
130
|
-
<InputOTPSlot index={0} />
|
|
131
|
-
<InputOTPSlot index={1} />
|
|
132
|
-
<InputOTPSlot index={2} />
|
|
133
|
-
</InputOTPGroup>
|
|
134
|
-
<InputOTPSeparator />
|
|
135
|
-
<InputOTPGroup>
|
|
136
|
-
<InputOTPSlot index={3} />
|
|
137
|
-
<InputOTPSlot index={4} />
|
|
138
|
-
<InputOTPSlot index={5} />
|
|
139
|
-
</InputOTPGroup>
|
|
140
|
-
</InputOTP>
|
|
141
|
-
<Button className="w-full mt-6" disabled={isSubmitting}>Verify</Button>
|
|
142
|
-
</Card>
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## Animation Storyboard
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
ANIMATION STORYBOARD
|
|
151
|
-
====================
|
|
152
|
-
BUDGET: 350ms | SPRING: gentle | REDUCED: opacity-only
|
|
153
|
-
|
|
154
|
-
T+0ms [layout] Split-screen panels visible (instant)
|
|
155
|
-
T+0ms [brand] Brand panel bg/shader (instant)
|
|
156
|
-
T+100ms [card] Auth card scales in {scaleIn, gentle}
|
|
157
|
-
T+200ms [logo] Logo fades in {fadeIn, snappy}
|
|
158
|
-
T+250ms [fields] Form fields stagger {blockStagger, 60ms, max 4}
|
|
159
|
-
T+350ms [cta] Sign-in button fades in {fadeIn, snappy}
|
|
160
|
-
|
|
161
|
-
REDUCED MOTION: Card and all children visible immediately
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## Required Components
|
|
167
|
-
|
|
168
|
-
| Component | Import Path | Purpose |
|
|
169
|
-
|-----------|-------------|---------|
|
|
170
|
-
| `AuthLayout` | `@vadimcomanescu/nadicode-design-system/auth-layout` | Split-screen wrapper |
|
|
171
|
-
| `LoginBlock` | `@vadimcomanescu/nadicode-design-system/login-block` | Pre-built login form |
|
|
172
|
-
| `SignUpBlock` | `@vadimcomanescu/nadicode-design-system/sign-up-block` | Pre-built signup form |
|
|
173
|
-
| `Card` | `@vadimcomanescu/nadicode-design-system/card` | Auth card container |
|
|
174
|
-
| `Input` | `@vadimcomanescu/nadicode-design-system/input` | Email, name fields |
|
|
175
|
-
| `PasswordInput` | `@vadimcomanescu/nadicode-design-system/password-input` | Password with toggle |
|
|
176
|
-
| `Label` | `@vadimcomanescu/nadicode-design-system/label` | Stacked labels |
|
|
177
|
-
| `Button` | `@vadimcomanescu/nadicode-design-system/button` | Submit, social login |
|
|
178
|
-
| `Alert` | `@vadimcomanescu/nadicode-design-system/alert` | Error messages |
|
|
179
|
-
| `Logo` | `@vadimcomanescu/nadicode-design-system/logo` | Brand mark |
|
|
180
|
-
| `BrandIcons` | `@vadimcomanescu/nadicode-design-system/brand-icons` | Google, GitHub icons |
|
|
181
|
-
| `Separator` | `@vadimcomanescu/nadicode-design-system/separator` | "Or" divider |
|
|
182
|
-
| `InputOTP` | `@vadimcomanescu/nadicode-design-system/input-otp` | 2FA code entry |
|
|
183
|
-
| `Spinner` | `@vadimcomanescu/nadicode-design-system/spinner` | Submit loading |
|
|
184
|
-
| `Typography` | `@vadimcomanescu/nadicode-design-system/typography` | Headings, descriptions |
|
|
185
|
-
|
|
186
|
-
### Allowed (optional)
|
|
187
|
-
|
|
188
|
-
`PasswordRecoveryBlock`, `ResetPasswordBlock`, `TwoFactorChallengeBlock`, `TwoFactorSetupBlock`, `AccountLockedBlock`, `AuthSuccessBlock`, `Checkbox` (remember me), `ShaderBackground`
|
|
189
|
-
|
|
190
|
-
### Forbidden
|
|
191
|
-
|
|
192
|
-
`Sidebar`, `DataTable`, chart components, `NavigationMenu`, decorative effects (except on brand panel)
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Required States
|
|
197
|
-
|
|
198
|
-
| State | Trigger | Visual |
|
|
199
|
-
|-------|---------|--------|
|
|
200
|
-
| `default` | Page loaded | Form ready for input |
|
|
201
|
-
| `submitting` | Form submitted | Button shows Spinner, form disabled |
|
|
202
|
-
| `error` | Auth failure | `Alert` variant="destructive" with message |
|
|
203
|
-
| `success` | Auth succeeded | Redirect to dashboard (or `AuthSuccessBlock`) |
|
|
204
|
-
| `2fa-challenge` | Server requests 2FA | Show 2FA code entry screen |
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Responsive Contract
|
|
209
|
-
|
|
210
|
-
| Breakpoint | Layout | Card Width |
|
|
211
|
-
|------------|--------|------------|
|
|
212
|
-
| Mobile | Centered card, no brand panel | Full width, max-w-md, px-4 |
|
|
213
|
-
| `lg:` | Split screen: brand (50%) + form (50%) | max-w-md centered in right half |
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## Styling Rules
|
|
218
|
-
|
|
219
|
-
- Auth card: `glass-floating p-8`
|
|
220
|
-
- Brand panel: full-height, may use `ShaderBackground` or illustration
|
|
221
|
-
- Labels: stacked above inputs (always)
|
|
222
|
-
- Social buttons: `variant="outline"`, 2-column grid
|
|
223
|
-
- Links: `text-link` token
|
|
224
|
-
- Error: `Alert` at top of form, not inline per-field (for auth errors)
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## Accessibility
|
|
229
|
-
|
|
230
|
-
- Form inputs have associated labels
|
|
231
|
-
- Error alert uses `role="alert"`
|
|
232
|
-
- Social login buttons include brand name in text
|
|
233
|
-
- OTP input is keyboard-navigable (auto-advance)
|
|
234
|
-
- Focus moves to first field on mount
|
|
235
|
-
- Escape key behavior is handled (no accidental navigation away)
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Reference Implementations
|
|
240
|
-
|
|
241
|
-
- `src/components/blocks/LoginBlock.tsx`
|
|
242
|
-
- `src/components/blocks/AuthLayout.tsx`
|
|
243
|
-
- `src/app/login/vanta/*/page.tsx` (7 variants)
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Verification
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
npx tsc --noEmit
|
|
251
|
-
npm run lint
|
|
252
|
-
npm run test
|
|
253
|
-
npx vitest run src/test/css-variable-usage.test.ts
|
|
254
|
-
```
|