@vadimcomanescu/nadicode-design-system 4.0.1 → 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.
Files changed (35) hide show
  1. package/.agents/skills/seed/SKILL.md +34 -163
  2. package/.agents/skills/seed/references/animation.md +2 -2
  3. package/.agents/skills/seed/references/responsive.md +1 -1
  4. package/README.md +2 -2
  5. package/eslint-rules/nadicode/rules/no-has-svg-selector.js +1 -1
  6. package/package.json +1 -2
  7. package/scripts/ds-check.mjs +0 -10
  8. package/scripts/sync-seed-skill.mjs +0 -3
  9. package/.agents/skills/seed/contract.md +0 -110
  10. package/.agents/skills/seed/intent-map.md +0 -320
  11. package/.agents/skills/seed/recipes/agency-home.md +0 -311
  12. package/.agents/skills/seed/recipes/agents-chat.md +0 -305
  13. package/.agents/skills/seed/recipes/analytics.md +0 -253
  14. package/.agents/skills/seed/recipes/auth.md +0 -254
  15. package/.agents/skills/seed/recipes/blog-content.md +0 -307
  16. package/.agents/skills/seed/recipes/checkout.md +0 -311
  17. package/.agents/skills/seed/recipes/company-about.md +0 -276
  18. package/.agents/skills/seed/recipes/company-contact.md +0 -234
  19. package/.agents/skills/seed/recipes/crud-form.md +0 -233
  20. package/.agents/skills/seed/recipes/crud-list-detail.md +0 -230
  21. package/.agents/skills/seed/recipes/dashboard.md +0 -354
  22. package/.agents/skills/seed/recipes/digital-workers.md +0 -314
  23. package/.agents/skills/seed/recipes/error-pages.md +0 -199
  24. package/.agents/skills/seed/recipes/marketing-landing.md +0 -293
  25. package/.agents/skills/seed/recipes/marketing-shell.md +0 -156
  26. package/.agents/skills/seed/recipes/navigation-shell.md +0 -787
  27. package/.agents/skills/seed/recipes/onboarding.md +0 -258
  28. package/.agents/skills/seed/recipes/pricing.md +0 -271
  29. package/.agents/skills/seed/recipes/service-detail.md +0 -302
  30. package/.agents/skills/seed/recipes/settings.md +0 -252
  31. package/.agents/skills/seed/references/blocks.md +0 -128
  32. package/.agents/skills/seed/references/components.md +0 -287
  33. package/.agents/skills/seed/references/icons.md +0 -169
  34. package/.agents/skills/seed/references/nextjs.md +0 -49
  35. package/.agents/skills/seed/references/tokens.md +0 -88
@@ -1,305 +0,0 @@
1
- # Recipe: Agent Chat
2
-
3
- 3-region agent workbench for AI agent interaction, tool monitoring, and artifact inspection.
4
-
5
- ## Route Patterns
6
-
7
- - `/agents`
8
- - `/voice-agents`
9
-
10
- ## Shell
11
-
12
- `app-shell` (Sidebar + top bar + SearchCommand)
13
-
14
- ---
15
-
16
- ## Layout Blueprint (Desktop)
17
-
18
- ```
19
- +--+------+---------------------------+---------+
20
- | | Team | Conversation | Work |
21
- |S | Panel| | Panel |
22
- |I | | [AgentMessageBubble] | |
23
- |D | Agent| [ToolCallCard] | [Tabs] |
24
- |E | list | [ThinkingIndicator] | Work |
25
- |B | with | [AgentMessageBubble] | Logs |
26
- |A | status| [ApprovalCard] | Files |
27
- |R | | | |
28
- | | Team | [AgentMessageBubble] | Code |
29
- | | metrics| | Diff |
30
- | | | | |
31
- | | +---------------------------+ Artifact|
32
- | | | Composer | Card |
33
- | | | [Textarea] [Send] | |
34
- +--+------+---------------------------+---------+
35
-
36
- Mobile: Conversation + Composer only.
37
- Team panel: left Sheet. Work panel: right Sheet.
38
- ```
39
-
40
- ---
41
-
42
- ## Section Sequence
43
-
44
- ### 1. Team & Status Panel (left, 280px)
45
-
46
- ```tsx
47
- <aside className="hidden xl:flex flex-col w-[280px] border-r border-border bg-surface/50">
48
- <div className="p-4 border-b border-border">
49
- <Heading level={4} size="title" >Team</Heading>
50
- </div>
51
- <ScrollArea className="flex-1">
52
- <AgentTeamPanel agents={agents} activeAgent={active} onSelect={setActive} />
53
- <div className="p-4 border-t border-border">
54
- <WorkflowGraph nodes={workflowNodes} edges={workflowEdges} />
55
- </div>
56
- <div className="p-4 mt-auto">
57
- <AgentMetricsCard metrics={runMetrics} />
58
- </div>
59
- </ScrollArea>
60
- <div className="p-4 border-t border-border">
61
- <ContextMeter used={contextUsed} total={contextTotal} />
62
- </div>
63
- </aside>
64
- ```
65
-
66
- ### 2. Conversation Region (center, flex-1)
67
-
68
- ```tsx
69
- <main className="flex-1 flex flex-col min-w-0">
70
- {/* Mobile header with panel triggers */}
71
- <header className="xl:hidden flex items-center gap-2 p-3 border-b border-border">
72
- <Sheet>
73
- <SheetTrigger asChild>
74
- <Button variant="ghost" size="icon"><UsersIcon size={16} /></Button>
75
- </SheetTrigger>
76
- <SheetContent side="left"><AgentTeamPanel ... /></SheetContent>
77
- </Sheet>
78
- <Heading level={4} size="title" className="flex-1 text-center truncate">
79
- {runTitle}
80
- </Heading>
81
- <Sheet>
82
- <SheetTrigger asChild>
83
- <Button variant="ghost" size="icon"><FileTextIcon size={16} /></Button>
84
- </SheetTrigger>
85
- <SheetContent side="right"><WorkPanel ... /></SheetContent>
86
- </Sheet>
87
- </header>
88
-
89
- {/* Message thread */}
90
- <ScrollArea className="flex-1 p-4" aria-live="polite">
91
- {messages.map(msg => {
92
- if (msg.type === "thinking") return <ThinkingIndicator key={msg.id} />
93
- if (msg.type === "tool") return (
94
- <ToolCallCard key={msg.id} name={msg.tool} args={msg.args}
95
- status={msg.status} result={msg.result} />
96
- )
97
- if (msg.type === "approval") return (
98
- <ApprovalCard key={msg.id} action={msg.action}
99
- onApprove={() => approve(msg.id)} onReject={() => reject(msg.id)} />
100
- )
101
- return (
102
- <AgentMessageBubble key={msg.id} role={msg.role}
103
- content={msg.content} isStreaming={msg.isStreaming} />
104
- )
105
- })}
106
- </ScrollArea>
107
-
108
- {/* Composer */}
109
- <div className="p-4 border-t border-border">
110
- <div className="flex items-end gap-2">
111
- <Textarea
112
- placeholder="Type a message..."
113
- className="flex-1 min-h-[44px] max-h-[200px]"
114
- value={input}
115
- onChange={e => setInput(e.target.value)}
116
- onKeyDown={handleKeyDown}
117
- />
118
- <Button onClick={handleSend} disabled={!input.trim() || isSending}>
119
- <SendIcon size={16} />
120
- </Button>
121
- </div>
122
- </div>
123
- </main>
124
- ```
125
-
126
- ### 3. Work Panel (right, 320px)
127
-
128
- ```tsx
129
- <aside className="hidden xl:flex flex-col w-[320px] border-l border-border">
130
- <Tabs value={workTab} onValueChange={setWorkTab} className="flex flex-col h-full">
131
- <TabsList className="mx-4 mt-4">
132
- <TabsTrigger value="work">Work</TabsTrigger>
133
- <TabsTrigger value="logs">Logs</TabsTrigger>
134
- <TabsTrigger value="files">Files</TabsTrigger>
135
- </TabsList>
136
- <ScrollArea className="flex-1">
137
- <TabsContent value="work" className="p-4 space-y-4">
138
- {artifacts.map(a => <ArtifactCard key={a.id} {...a} />)}
139
- </TabsContent>
140
- <TabsContent value="logs" className="p-4">
141
- <AgentTerminal lines={logLines} />
142
- </TabsContent>
143
- <TabsContent value="files" className="p-4 space-y-4">
144
- {diffs.map(d => <CodeDiffViewer key={d.file} {...d} />)}
145
- </TabsContent>
146
- </ScrollArea>
147
- </Tabs>
148
- </aside>
149
- ```
150
-
151
- ---
152
-
153
- ## Animation Storyboard
154
-
155
- ```
156
- ANIMATION STORYBOARD
157
- ====================
158
- BUDGET: 300ms (shell) | STREAMING: continuous | REDUCED: opacity-only
159
-
160
- T+0ms [shell] All panels visible (instant)
161
- T+50ms [team] Team panel content fades in {fadeIn, snappy}
162
- T+100ms [messages] Message history fades in {fadeIn, snappy}
163
- T+200ms [work] Work panel content fades in {fadeIn, snappy}
164
-
165
- NEW MESSAGE (runtime):
166
- T+0ms [bubble] Message slides up from bottom {slideInUp, snappy, y: 16px}
167
-
168
- TOOL CALL (runtime):
169
- T+0ms [toolcard] Card expands in-place {scaleIn, snappy}
170
- T+0ms [status] Status badge animates {fadeIn, micro}
171
-
172
- THINKING (runtime):
173
- T+0ms [dots] Pulsing dot animation (continuous CSS)
174
-
175
- APPROVAL (runtime):
176
- T+0ms [card] ApprovalCard scales in {scaleIn, gentle}
177
-
178
- REDUCED MOTION: Items appear instantly, no slide/scale
179
- ```
180
-
181
- ---
182
-
183
- ## Required Components
184
-
185
- ### Chat Primitives (preferred)
186
-
187
- | Component | Import Path | Purpose |
188
- |-----------|-------------|---------|
189
- | `Conversation` | `.../conversation` | Scroll-aware container with auto-scroll |
190
- | `ChatMessage` | `.../chat-message` | Core message with avatar, content, actions |
191
- | `ChatResponse` | `.../chat-response` | Streaming markdown response renderer |
192
- | `ChatPromptInput` | `.../chat-prompt-input` | Chat text input with keyboard handling |
193
- | `ChatToolCall` | `.../chat-tool-call` | Tool call lifecycle wrapper |
194
- | `ChatActions` | `.../chat-actions` | Copy, retry, edit action buttons |
195
- | `ChatGreeting` | `.../chat-greeting` | Welcome greeting for sessions |
196
- | `ChatThinkingMessage` | `.../chat-thinking-message` | Animated thinking state |
197
- | `ChatShimmer` | `.../chat-shimmer` | Loading shimmer placeholder |
198
- | `ChatReasoning` | `.../chat-reasoning` | AI reasoning with auto-close |
199
- | `ChatConfirmation` | `.../chat-confirmation` | Action confirmation dialog |
200
- | `ChatSuggestion` | `.../chat-suggestion` | Follow-up prompt chips |
201
- | `ChatSources` | `.../chat-sources` | Source citations panel |
202
- | `ChatBranch` | `.../chat-branch` | Conversation fork navigation |
203
- | `ChatChainOfThought` | `.../chat-chain-of-thought` | Step-by-step reasoning |
204
- | `ChatPlan` | `.../chat-plan` | Collapsible plan card |
205
- | `ChatQueue` | `.../chat-queue` | Task queue with sections |
206
- | `ChatPromptInputAttachments` | `.../chat-prompt-input-attachments` | File attachment support |
207
-
208
- ### Agent-Level Components
209
-
210
- | Component | Import Path | Purpose |
211
- |-----------|-------------|---------|
212
- | `AgentTeamPanel` | `.../agent-team-panel` | Team member list |
213
- | `AgentStatus` | `.../agent-status` | Connection status |
214
- | `AgentTimeline` | `.../agent-timeline` | Action timeline |
215
- | `AgentMetricsCard` | `.../agent-metrics-card` | Run metrics |
216
- | `ConversationThread` | `.../conversation-thread` | Legacy message rendering |
217
- | `AgentMessageBubble` | `.../agent-message-bubble` | Individual messages |
218
- | `ThinkingIndicator` | `.../thinking-indicator` | Processing state |
219
- | `ToolCallCard` | `.../tool-call-card` | Tool invocations |
220
- | `ApprovalCard` | `.../approval-card` | Human approval flow |
221
- | `CodeDiffViewer` | `.../code-diff-viewer` | Code changes |
222
- | `ArtifactCard` | `.../artifact-card` | Generated outputs |
223
- | `AgentTerminal` | `.../agent-terminal` | Command output |
224
- | `WorkflowGraph` | `.../workflow-graph` | DAG execution flow |
225
- | `ContextMeter` | `.../context-meter` | Context window usage |
226
- | `SourceCitation` | `.../source-citation` | Referenced sources |
227
- | `Tabs` | `.../tabs` | Work panel tabs |
228
- | `Button` | `.../button` | Send, panel triggers |
229
- | `ScrollArea` | `.../scroll-area` | Scrollable regions |
230
- | `Sheet` | `.../sheet` | Mobile panel drawers |
231
-
232
- ### Allowed (optional)
233
-
234
- `HandoffIndicator`, `MemoryInspector`, `StreamingText`, `Badge`, `Avatar`, `AgentAvatar`, `Resizable`
235
-
236
- ### Forbidden
237
-
238
- `HeroBlock`, `PricingBlock`, `FormWizard`, `DataTable`, marketing blocks, decorative effects
239
-
240
- ---
241
-
242
- ## Required States
243
-
244
- | State | Trigger | Visual |
245
- |-------|---------|--------|
246
- | `empty` | No active run | `Empty` with "Start a conversation" message |
247
- | `loading` | History loading | Skeleton message bubbles |
248
- | `running` | Agent(s) active | Live conversation with streaming |
249
- | `thinking` | Agent processing | `ThinkingIndicator` in message thread |
250
- | `blocked-approval` | Awaiting user action | `ApprovalCard` prominent in thread |
251
- | `failed` | Run or tool error | Error message in thread + retry option |
252
- | `complete` | Run finished | Final message with artifacts summary |
253
- | `over-budget` | Cost/token threshold exceeded | Warning badge on metrics, pause prompt |
254
-
255
- ---
256
-
257
- ## Responsive Contract
258
-
259
- | Breakpoint | Team Panel | Conversation | Work Panel |
260
- |------------|------------|-------------|------------|
261
- | Mobile | Hidden (Sheet, left) | Full width + composer | Hidden (Sheet, right) |
262
- | `lg:` | Sidebar 280px | Flex-1 | Hidden (Sheet) |
263
- | `xl:` | Sidebar 280px | Flex-1 | Panel 320px |
264
-
265
- ---
266
-
267
- ## Styling Rules
268
-
269
- - Panel backgrounds: `bg-surface/50` or `bg-background`
270
- - Panel borders: `border-border`
271
- - Message bubbles: styled by `AgentMessageBubble` (role-based)
272
- - Tool call cards: `glass-panel` with status color
273
- - Composer: `border-t border-border` with `p-4`
274
- - No raw palette colors
275
-
276
- ---
277
-
278
- ## Accessibility
279
-
280
- - Message thread uses `aria-live="polite"` for streaming updates
281
- - All interactive controls have visible focus rings
282
- - Panel toggles on mobile have `aria-label`
283
- - Composer textarea has `aria-label="Message input"`
284
- - Approval buttons are clearly labeled (approve/reject)
285
- - Tab navigation for work panel is keyboard accessible
286
-
287
- ---
288
-
289
- ## Reference Implementations
290
-
291
- - `src/app/voice-agents/page.tsx`
292
- - `src/components/pages/VoiceAgentsPage.tsx`
293
- - `src/components/blocks/AgentConversationBlock.tsx`
294
- - `src/components/blocks/ChatLayout.tsx`
295
-
296
- ---
297
-
298
- ## Verification
299
-
300
- ```bash
301
- npx tsc --noEmit
302
- npm run lint
303
- npm run test
304
- npx vitest run src/test/css-variable-usage.test.ts
305
- ```
@@ -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
- ```