wiggum-cli 0.1.0
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/LICENSE +21 -0
- package/README.md +341 -0
- package/bin/ralph.js +8 -0
- package/dist/ai/enhancer.d.ts +100 -0
- package/dist/ai/enhancer.d.ts.map +1 -0
- package/dist/ai/enhancer.js +233 -0
- package/dist/ai/enhancer.js.map +1 -0
- package/dist/ai/index.d.ts +8 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +11 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts.d.ts +26 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +201 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/providers.d.ts +35 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +104 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +196 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +124 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/monitor.d.ts +17 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +342 -0
- package/dist/commands/monitor.js.map +1 -0
- package/dist/commands/new.d.ts +19 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +272 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/run.d.ts +16 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +175 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/generator/config.d.ts +59 -0
- package/dist/generator/config.d.ts.map +1 -0
- package/dist/generator/config.js +68 -0
- package/dist/generator/config.js.map +1 -0
- package/dist/generator/index.d.ts +64 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +147 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/templates.d.ts +70 -0
- package/dist/generator/templates.d.ts.map +1 -0
- package/dist/generator/templates.js +296 -0
- package/dist/generator/templates.js.map +1 -0
- package/dist/generator/writer.d.ts +93 -0
- package/dist/generator/writer.d.ts.map +1 -0
- package/dist/generator/writer.js +213 -0
- package/dist/generator/writer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner/detectors/core/framework.d.ts +11 -0
- package/dist/scanner/detectors/core/framework.d.ts.map +1 -0
- package/dist/scanner/detectors/core/framework.js +275 -0
- package/dist/scanner/detectors/core/framework.js.map +1 -0
- package/dist/scanner/detectors/core/packageManager.d.ts +11 -0
- package/dist/scanner/detectors/core/packageManager.d.ts.map +1 -0
- package/dist/scanner/detectors/core/packageManager.js +74 -0
- package/dist/scanner/detectors/core/packageManager.js.map +1 -0
- package/dist/scanner/detectors/core/styling.d.ts +12 -0
- package/dist/scanner/detectors/core/styling.d.ts.map +1 -0
- package/dist/scanner/detectors/core/styling.js +230 -0
- package/dist/scanner/detectors/core/styling.js.map +1 -0
- package/dist/scanner/detectors/core/testing.d.ts +12 -0
- package/dist/scanner/detectors/core/testing.d.ts.map +1 -0
- package/dist/scanner/detectors/core/testing.js +190 -0
- package/dist/scanner/detectors/core/testing.js.map +1 -0
- package/dist/scanner/detectors/data/api.d.ts +12 -0
- package/dist/scanner/detectors/data/api.d.ts.map +1 -0
- package/dist/scanner/detectors/data/api.js +261 -0
- package/dist/scanner/detectors/data/api.js.map +1 -0
- package/dist/scanner/detectors/data/database.d.ts +12 -0
- package/dist/scanner/detectors/data/database.d.ts.map +1 -0
- package/dist/scanner/detectors/data/database.js +213 -0
- package/dist/scanner/detectors/data/database.js.map +1 -0
- package/dist/scanner/detectors/data/orm.d.ts +12 -0
- package/dist/scanner/detectors/data/orm.d.ts.map +1 -0
- package/dist/scanner/detectors/data/orm.js +160 -0
- package/dist/scanner/detectors/data/orm.js.map +1 -0
- package/dist/scanner/detectors/frontend/formHandling.d.ts +12 -0
- package/dist/scanner/detectors/frontend/formHandling.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/formHandling.js +211 -0
- package/dist/scanner/detectors/frontend/formHandling.js.map +1 -0
- package/dist/scanner/detectors/frontend/stateManagement.d.ts +12 -0
- package/dist/scanner/detectors/frontend/stateManagement.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/stateManagement.js +221 -0
- package/dist/scanner/detectors/frontend/stateManagement.js.map +1 -0
- package/dist/scanner/detectors/frontend/uiComponents.d.ts +12 -0
- package/dist/scanner/detectors/frontend/uiComponents.d.ts.map +1 -0
- package/dist/scanner/detectors/frontend/uiComponents.js +285 -0
- package/dist/scanner/detectors/frontend/uiComponents.js.map +1 -0
- package/dist/scanner/detectors/infra/deployment.d.ts +12 -0
- package/dist/scanner/detectors/infra/deployment.d.ts.map +1 -0
- package/dist/scanner/detectors/infra/deployment.js +301 -0
- package/dist/scanner/detectors/infra/deployment.js.map +1 -0
- package/dist/scanner/detectors/infra/monorepo.d.ts +12 -0
- package/dist/scanner/detectors/infra/monorepo.d.ts.map +1 -0
- package/dist/scanner/detectors/infra/monorepo.js +219 -0
- package/dist/scanner/detectors/infra/monorepo.js.map +1 -0
- package/dist/scanner/detectors/mcp/mcpProject.d.ts +12 -0
- package/dist/scanner/detectors/mcp/mcpProject.d.ts.map +1 -0
- package/dist/scanner/detectors/mcp/mcpProject.js +154 -0
- package/dist/scanner/detectors/mcp/mcpProject.js.map +1 -0
- package/dist/scanner/detectors/mcp/mcpServers.d.ts +17 -0
- package/dist/scanner/detectors/mcp/mcpServers.d.ts.map +1 -0
- package/dist/scanner/detectors/mcp/mcpServers.js +193 -0
- package/dist/scanner/detectors/mcp/mcpServers.js.map +1 -0
- package/dist/scanner/detectors/services/analytics.d.ts +12 -0
- package/dist/scanner/detectors/services/analytics.d.ts.map +1 -0
- package/dist/scanner/detectors/services/analytics.js +236 -0
- package/dist/scanner/detectors/services/analytics.js.map +1 -0
- package/dist/scanner/detectors/services/auth.d.ts +12 -0
- package/dist/scanner/detectors/services/auth.d.ts.map +1 -0
- package/dist/scanner/detectors/services/auth.js +217 -0
- package/dist/scanner/detectors/services/auth.js.map +1 -0
- package/dist/scanner/detectors/services/email.d.ts +12 -0
- package/dist/scanner/detectors/services/email.d.ts.map +1 -0
- package/dist/scanner/detectors/services/email.js +211 -0
- package/dist/scanner/detectors/services/email.js.map +1 -0
- package/dist/scanner/detectors/services/payments.d.ts +12 -0
- package/dist/scanner/detectors/services/payments.d.ts.map +1 -0
- package/dist/scanner/detectors/services/payments.js +185 -0
- package/dist/scanner/detectors/services/payments.js.map +1 -0
- package/dist/scanner/detectors/utils.d.ts +160 -0
- package/dist/scanner/detectors/utils.d.ts.map +1 -0
- package/dist/scanner/detectors/utils.js +222 -0
- package/dist/scanner/detectors/utils.js.map +1 -0
- package/dist/scanner/index.d.ts +42 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +282 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/registry.d.ts +43 -0
- package/dist/scanner/registry.d.ts.map +1 -0
- package/dist/scanner/registry.js +243 -0
- package/dist/scanner/registry.js.map +1 -0
- package/dist/scanner/types.d.ts +112 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +6 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/templates/config/ralph.config.js.tmpl +38 -0
- package/dist/templates/guides/AGENTS.md.tmpl +100 -0
- package/dist/templates/guides/FRONTEND.md.tmpl +523 -0
- package/dist/templates/guides/PERFORMANCE.md.tmpl +264 -0
- package/dist/templates/guides/SECURITY.md.tmpl +100 -0
- package/dist/templates/prompts/PROMPT.md.tmpl +77 -0
- package/dist/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
- package/dist/templates/prompts/PROMPT_feature.md.tmpl +83 -0
- package/dist/templates/prompts/PROMPT_review.md.tmpl +167 -0
- package/dist/templates/prompts/PROMPT_verify.md.tmpl +72 -0
- package/dist/templates/root/.gitignore.tmpl +5 -0
- package/dist/templates/root/LEARNINGS.md.tmpl +24 -0
- package/dist/templates/root/README.md.tmpl +61 -0
- package/dist/templates/scripts/feature-loop.sh.tmpl +267 -0
- package/dist/templates/scripts/loop.sh.tmpl +59 -0
- package/dist/templates/scripts/ralph-monitor.sh.tmpl +244 -0
- package/dist/templates/specs/README.md.tmpl +57 -0
- package/dist/templates/specs/_example.md.tmpl +71 -0
- package/dist/utils/config.d.ts +95 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +148 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/header.d.ts +5 -0
- package/dist/utils/header.d.ts.map +1 -0
- package/dist/utils/header.js +15 -0
- package/dist/utils/header.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +24 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +44 -0
- package/src/ai/enhancer.ts +350 -0
- package/src/ai/index.ts +38 -0
- package/src/ai/prompts.ts +217 -0
- package/src/ai/providers.ts +136 -0
- package/src/cli.ts +255 -0
- package/src/commands/init.ts +149 -0
- package/src/commands/monitor.ts +412 -0
- package/src/commands/new.ts +312 -0
- package/src/commands/run.ts +214 -0
- package/src/generator/config.ts +116 -0
- package/src/generator/index.ts +227 -0
- package/src/generator/templates.ts +412 -0
- package/src/generator/writer.ts +293 -0
- package/src/index.ts +41 -0
- package/src/scanner/detectors/core/framework.ts +332 -0
- package/src/scanner/detectors/core/packageManager.ts +91 -0
- package/src/scanner/detectors/core/styling.ts +261 -0
- package/src/scanner/detectors/core/testing.ts +221 -0
- package/src/scanner/detectors/data/api.ts +303 -0
- package/src/scanner/detectors/data/database.ts +245 -0
- package/src/scanner/detectors/data/orm.ts +180 -0
- package/src/scanner/detectors/frontend/formHandling.ts +244 -0
- package/src/scanner/detectors/frontend/stateManagement.ts +261 -0
- package/src/scanner/detectors/frontend/uiComponents.ts +328 -0
- package/src/scanner/detectors/infra/deployment.ts +343 -0
- package/src/scanner/detectors/infra/monorepo.ts +251 -0
- package/src/scanner/detectors/mcp/mcpProject.ts +176 -0
- package/src/scanner/detectors/mcp/mcpServers.ts +237 -0
- package/src/scanner/detectors/services/analytics.ts +273 -0
- package/src/scanner/detectors/services/auth.ts +254 -0
- package/src/scanner/detectors/services/email.ts +244 -0
- package/src/scanner/detectors/services/payments.ts +213 -0
- package/src/scanner/detectors/utils.ts +251 -0
- package/src/scanner/index.ts +354 -0
- package/src/scanner/registry.ts +301 -0
- package/src/scanner/types.ts +152 -0
- package/src/templates/config/ralph.config.js.tmpl +38 -0
- package/src/templates/guides/AGENTS.md.tmpl +100 -0
- package/src/templates/guides/FRONTEND.md.tmpl +523 -0
- package/src/templates/guides/PERFORMANCE.md.tmpl +264 -0
- package/src/templates/guides/SECURITY.md.tmpl +100 -0
- package/src/templates/prompts/PROMPT.md.tmpl +77 -0
- package/src/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
- package/src/templates/prompts/PROMPT_feature.md.tmpl +83 -0
- package/src/templates/prompts/PROMPT_review.md.tmpl +167 -0
- package/src/templates/prompts/PROMPT_verify.md.tmpl +72 -0
- package/src/templates/root/.gitignore.tmpl +5 -0
- package/src/templates/root/LEARNINGS.md.tmpl +24 -0
- package/src/templates/root/README.md.tmpl +61 -0
- package/src/templates/scripts/feature-loop.sh.tmpl +267 -0
- package/src/templates/scripts/loop.sh.tmpl +59 -0
- package/src/templates/scripts/ralph-monitor.sh.tmpl +244 -0
- package/src/templates/specs/README.md.tmpl +57 -0
- package/src/templates/specs/_example.md.tmpl +71 -0
- package/src/utils/config.ts +221 -0
- package/src/utils/header.ts +15 -0
- package/src/utils/logger.ts +28 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# Frontend Design Guide
|
|
2
|
+
|
|
3
|
+
Comprehensive UI/UX reference for building polished, production-grade interfaces.
|
|
4
|
+
|
|
5
|
+
## Design Thinking
|
|
6
|
+
|
|
7
|
+
Before coding, understand the context:
|
|
8
|
+
|
|
9
|
+
### Purpose-Driven Design
|
|
10
|
+
- **What problem does this solve?** Every component should have a clear job.
|
|
11
|
+
- **Who uses it?** Consider the user's context, expertise, and goals.
|
|
12
|
+
- **What's the hierarchy?** Emphasize what matters most.
|
|
13
|
+
|
|
14
|
+
### Visual Principles
|
|
15
|
+
- **Hierarchy**: Guide the eye - primary action should be obvious
|
|
16
|
+
- **Consistency**: Predictable patterns reduce cognitive load
|
|
17
|
+
- **Feedback**: Every action should have visible response
|
|
18
|
+
- **Proximity**: Related items should be visually grouped
|
|
19
|
+
- **Contrast**: Use difference to create emphasis
|
|
20
|
+
|
|
21
|
+
### Questions Before Building
|
|
22
|
+
1. What existing patterns can I follow? (Search codebase first)
|
|
23
|
+
2. What states does this need? (empty, loading, error, success)
|
|
24
|
+
3. How does this look on mobile?
|
|
25
|
+
4. What happens when there's lots of data? Or none?
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Anti-Patterns (AI Slop to Avoid)
|
|
30
|
+
|
|
31
|
+
These patterns make UI look generated, not designed:
|
|
32
|
+
|
|
33
|
+
| Anti-Pattern | Problem | Fix |
|
|
34
|
+
|--------------|---------|-----|
|
|
35
|
+
| Generic layout | No visual hierarchy | Emphasize primary content, de-emphasize secondary |
|
|
36
|
+
| Missing interaction states | Dead-feeling UI | Add hover, focus, active, disabled states |
|
|
37
|
+
| Charts without context | Data with no meaning | Add title, labels, legend, tooltips |
|
|
38
|
+
| Forms without feedback | Users confused | Show validation inline, success/error states |
|
|
39
|
+
| Empty = blank | Wasted opportunity | Helpful message + call to action |
|
|
40
|
+
| Hard-coded colors | Inconsistent, hard to maintain | Use CSS variables / {{styling}} classes |
|
|
41
|
+
| Walls of text | Overwhelming | Break into sections, use headings, whitespace |
|
|
42
|
+
| All same-sized elements | Flat, boring | Vary size to create hierarchy |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Layout Principles
|
|
47
|
+
|
|
48
|
+
### Grid & Spacing
|
|
49
|
+
- Use consistent spacing scale ({{styling}}: 2, 4, 6, 8, 12, 16, 24, 32)
|
|
50
|
+
- Group related items with less space between them
|
|
51
|
+
- More space separates distinct sections
|
|
52
|
+
- Content should breathe - don't cram
|
|
53
|
+
|
|
54
|
+
### Responsive Breakpoints
|
|
55
|
+
```
|
|
56
|
+
Mobile: < 640px (sm:)
|
|
57
|
+
Tablet: >= 640px (md:)
|
|
58
|
+
Desktop: >= 1024px (lg:)
|
|
59
|
+
Wide: >= 1280px (xl:)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Mobile-First Approach
|
|
63
|
+
1. Design for mobile constraint first
|
|
64
|
+
2. Add complexity as screen grows
|
|
65
|
+
3. Touch targets: minimum 44x44px
|
|
66
|
+
4. Stack on mobile, side-by-side on desktop
|
|
67
|
+
|
|
68
|
+
### Common Layouts
|
|
69
|
+
- **Dashboard**: Grid of cards, stats at top
|
|
70
|
+
- **Form**: Single column, labels above inputs
|
|
71
|
+
- **Settings**: Two-column on desktop (nav + content)
|
|
72
|
+
- **List**: Full width with filters, pagination
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Component Guidelines
|
|
77
|
+
|
|
78
|
+
### State Matrix
|
|
79
|
+
Every interactive component needs these states:
|
|
80
|
+
|
|
81
|
+
| State | Visual Treatment |
|
|
82
|
+
|-------|------------------|
|
|
83
|
+
| Default | Base styling |
|
|
84
|
+
| Hover | Subtle highlight (background shift) |
|
|
85
|
+
| Focus | Visible ring (accessibility requirement) |
|
|
86
|
+
| Active/Pressed | Slightly darker/smaller |
|
|
87
|
+
| Disabled | Reduced opacity, no cursor pointer |
|
|
88
|
+
| Loading | Spinner or skeleton, disabled interaction |
|
|
89
|
+
| Error | Red/destructive color, error message |
|
|
90
|
+
|
|
91
|
+
### Component Selection Guide
|
|
92
|
+
|
|
93
|
+
| Need | Component | When to Use |
|
|
94
|
+
|------|-----------|-------------|
|
|
95
|
+
| Primary action | `Button variant="default"` | Main CTA per page/card |
|
|
96
|
+
| Secondary action | `Button variant="outline"` | Alternative actions |
|
|
97
|
+
| Destructive | `Button variant="destructive"` | Delete, remove, cancel subscription |
|
|
98
|
+
| Navigation | Link or ghost button | Moving between pages |
|
|
99
|
+
| Selection (1 of many) | Radio / Select | Limited options (< 7) |
|
|
100
|
+
| Selection (many of many) | Checkbox | Multiple selections |
|
|
101
|
+
| Text input | Input | Single line |
|
|
102
|
+
| Long text | Textarea | Multi-line content |
|
|
103
|
+
| On/Off | Switch | Boolean settings |
|
|
104
|
+
| Feedback | Toast | Transient messages |
|
|
105
|
+
| Confirmation | AlertDialog | Destructive actions |
|
|
106
|
+
|
|
107
|
+
### Accessibility Requirements (WCAG 2.1)
|
|
108
|
+
|
|
109
|
+
Accessibility isn't optional - it's foundational to good design.
|
|
110
|
+
|
|
111
|
+
**Critical (must fix immediately):**
|
|
112
|
+
- Missing alt text on images
|
|
113
|
+
- Unlabeled buttons (add `aria-label` for icon-only buttons)
|
|
114
|
+
- Non-semantic click handlers (use `<button>` not `<div onClick>`)
|
|
115
|
+
|
|
116
|
+
**Serious:**
|
|
117
|
+
- Removed focus states (never remove `:focus-visible` ring)
|
|
118
|
+
- Missing keyboard support (all flows must be keyboard-operable)
|
|
119
|
+
- Inadequate touch targets (minimum 44x44px mobile, 24x24px desktop)
|
|
120
|
+
|
|
121
|
+
**Standards:**
|
|
122
|
+
- All interactive elements keyboard accessible
|
|
123
|
+
- Focus order follows visual order
|
|
124
|
+
- Color not the only indicator (add icons/text)
|
|
125
|
+
- Sufficient contrast (4.5:1 for text, consider APCA for perceptual accuracy)
|
|
126
|
+
- Form inputs have explicit visible labels
|
|
127
|
+
- Use `:focus-visible` to show focus only for keyboard users
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Data Visualization
|
|
132
|
+
|
|
133
|
+
### Chart Type Selection
|
|
134
|
+
|
|
135
|
+
| Data Type | Chart | Example |
|
|
136
|
+
|-----------|-------|---------|
|
|
137
|
+
| Part of whole | Pie/Donut | Response distribution |
|
|
138
|
+
| Comparison | Bar (horizontal) | Rating breakdown |
|
|
139
|
+
| Trend over time | Line/Area | Responses per day |
|
|
140
|
+
| Distribution | Bar (vertical) | Survey channels |
|
|
141
|
+
| Correlation | Scatter | (rare in this app) |
|
|
142
|
+
|
|
143
|
+
### Required Chart Elements
|
|
144
|
+
Every chart MUST have:
|
|
145
|
+
- [ ] **Title**: What data is this?
|
|
146
|
+
- [ ] **Labels**: Axis labels or segment labels
|
|
147
|
+
- [ ] **Tooltip**: Details on hover
|
|
148
|
+
- [ ] **Legend**: If multiple series
|
|
149
|
+
- [ ] **Empty state**: When no data
|
|
150
|
+
|
|
151
|
+
### Chart Pattern
|
|
152
|
+
```tsx
|
|
153
|
+
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'
|
|
154
|
+
|
|
155
|
+
// Always define a config
|
|
156
|
+
const chartConfig = {
|
|
157
|
+
value: { label: 'Responses', color: 'hsl(var(--chart-1))' },
|
|
158
|
+
} satisfies ChartConfig
|
|
159
|
+
|
|
160
|
+
// Use ChartContainer for consistent sizing
|
|
161
|
+
<ChartContainer config={chartConfig} className="h-[300px]">
|
|
162
|
+
<BarChart data={data}>
|
|
163
|
+
<XAxis dataKey="name" />
|
|
164
|
+
<YAxis />
|
|
165
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
166
|
+
<Bar dataKey="value" fill="var(--color-value)" radius={4} />
|
|
167
|
+
</BarChart>
|
|
168
|
+
</ChartContainer>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Chart Colors
|
|
172
|
+
Use semantic color tokens, not raw values:
|
|
173
|
+
```css
|
|
174
|
+
--chart-1: Primary data
|
|
175
|
+
--chart-2: Secondary data
|
|
176
|
+
--chart-3 through --chart-5: Additional series
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Visual Polish for Charts
|
|
180
|
+
- Add `radius` to bars for softer appearance
|
|
181
|
+
- Use gradients for area charts (gradient fills)
|
|
182
|
+
- Animate on load with `animationDuration`
|
|
183
|
+
- Format numbers in tooltips (e.g., percentages, currency)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Micro-Interactions
|
|
188
|
+
|
|
189
|
+
### Loading States
|
|
190
|
+
| Duration | Treatment |
|
|
191
|
+
|----------|-----------|
|
|
192
|
+
| < 300ms | No indicator needed |
|
|
193
|
+
| 300ms - 2s | Spinner or button loading state |
|
|
194
|
+
| > 2s | Skeleton or progress indicator |
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
// Button loading
|
|
198
|
+
<Button disabled={isLoading}>
|
|
199
|
+
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
200
|
+
{isLoading ? 'Saving...' : 'Save'}
|
|
201
|
+
</Button>
|
|
202
|
+
|
|
203
|
+
// Skeleton for content
|
|
204
|
+
<Skeleton className="h-4 w-[250px]" />
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Empty States
|
|
208
|
+
Never show a blank space. Always:
|
|
209
|
+
1. Explain what would be here
|
|
210
|
+
2. Offer a path forward
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
// Good empty state
|
|
214
|
+
<div className="text-center py-12">
|
|
215
|
+
<BarChart3 className="mx-auto h-12 w-12 text-muted-foreground" />
|
|
216
|
+
<h3 className="mt-4 text-lg font-medium">No responses yet</h3>
|
|
217
|
+
<p className="mt-2 text-sm text-muted-foreground">
|
|
218
|
+
Share your survey to start collecting data
|
|
219
|
+
</p>
|
|
220
|
+
<Button className="mt-4">Copy Survey Link</Button>
|
|
221
|
+
</div>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Error States
|
|
225
|
+
- Use `destructive` variant colors
|
|
226
|
+
- Show what went wrong (simply)
|
|
227
|
+
- Offer retry or alternative
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
<Alert variant="destructive">
|
|
231
|
+
<AlertCircle className="h-4 w-4" />
|
|
232
|
+
<AlertTitle>Failed to load data</AlertTitle>
|
|
233
|
+
<AlertDescription>
|
|
234
|
+
Please try refreshing the page.
|
|
235
|
+
<Button variant="link" onClick={retry}>Retry</Button>
|
|
236
|
+
</AlertDescription>
|
|
237
|
+
</Alert>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Animation & Transitions
|
|
241
|
+
|
|
242
|
+
**Performance rules:**
|
|
243
|
+
- Only animate GPU-accelerated properties: `transform`, `opacity`
|
|
244
|
+
- Never animate layout properties (`width`, `height`, `top`, `left`)
|
|
245
|
+
- Avoid `transition: all` - explicitly list properties
|
|
246
|
+
- Keep interactions under 200ms
|
|
247
|
+
- Remove `will-change` when animation completes
|
|
248
|
+
|
|
249
|
+
**User preferences:**
|
|
250
|
+
- Always respect `prefers-reduced-motion`
|
|
251
|
+
```tsx
|
|
252
|
+
// Check user preference
|
|
253
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
254
|
+
|
|
255
|
+
// Or use {{styling}}
|
|
256
|
+
<div className="motion-safe:animate-fade-in motion-reduce:animate-none">
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Duration guidelines:**
|
|
260
|
+
- Hovers: 150-200ms
|
|
261
|
+
- State changes: 200-300ms
|
|
262
|
+
- Page transitions: 300-500ms
|
|
263
|
+
- Ease: `ease-in-out` for most, `ease-out` for exits
|
|
264
|
+
|
|
265
|
+
**Don't:**
|
|
266
|
+
- Add motion without explicit purpose
|
|
267
|
+
- Use custom easing curves without request
|
|
268
|
+
- Animate large images or complex layouts
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Forms
|
|
273
|
+
|
|
274
|
+
### Input Behavior
|
|
275
|
+
- **Enter key**: Submits single-control forms immediately
|
|
276
|
+
- **Cmd/Ctrl+Enter**: Submits in textareas (multi-line inputs)
|
|
277
|
+
- **Never block paste** - even for number-only fields
|
|
278
|
+
- **Never disable typing** - allow any input, validate on submit
|
|
279
|
+
|
|
280
|
+
### Validation
|
|
281
|
+
- Show errors **next to the field**, not in a banner
|
|
282
|
+
- Focus the **first error field** on submit failure
|
|
283
|
+
- Use inline validation for complex fields (email, password strength)
|
|
284
|
+
- Error messages should be instructional, not just descriptive
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
// Good: Error next to field
|
|
288
|
+
<div className="space-y-2">
|
|
289
|
+
<Label htmlFor="email">Email</Label>
|
|
290
|
+
<Input id="email" aria-invalid={!!errors.email} />
|
|
291
|
+
{errors.email && (
|
|
292
|
+
<p className="text-sm text-destructive">{errors.email.message}</p>
|
|
293
|
+
)}
|
|
294
|
+
</div>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Labels & Targets
|
|
298
|
+
- Every input needs an explicit `<Label>` (not just placeholder)
|
|
299
|
+
- No dead zones on checkboxes/radios - label should be clickable
|
|
300
|
+
- Enable password manager compatibility (proper `name` and `type` attributes)
|
|
301
|
+
|
|
302
|
+
### Destructive Actions
|
|
303
|
+
- Always use `AlertDialog` for destructive actions (delete, remove)
|
|
304
|
+
- Provide undo functionality when possible
|
|
305
|
+
- Require confirmation for irreversible actions
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## URL & State Persistence
|
|
310
|
+
|
|
311
|
+
Deep-link everything users might want to share or bookmark:
|
|
312
|
+
|
|
313
|
+
- **Filters**: `?status=active&sort=date`
|
|
314
|
+
- **Tabs**: `?tab=settings`
|
|
315
|
+
- **Pagination**: `?page=2`
|
|
316
|
+
- **Expanded panels**: `?section=advanced`
|
|
317
|
+
- **Search queries**: `?q=search+term`
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
// Use URL state instead of React state for shareable UI
|
|
321
|
+
import { useSearchParams } from 'next/navigation'
|
|
322
|
+
|
|
323
|
+
const [searchParams, setSearchParams] = useSearchParams()
|
|
324
|
+
const activeTab = searchParams.get('tab') ?? 'overview'
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Optimistic updates**: Update UI immediately on likely success, reconcile with server response. Don't make users wait for round-trips on common actions.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Performance
|
|
332
|
+
|
|
333
|
+
### Response Time Targets
|
|
334
|
+
- **Optimistic UI**: Update immediately, sync in background
|
|
335
|
+
- **POST/PATCH/DELETE**: Target under 500ms
|
|
336
|
+
- **Large lists**: Virtualize (react-virtual, tanstack-virtual)
|
|
337
|
+
|
|
338
|
+
### Layout Stability
|
|
339
|
+
- Set explicit `width` and `height` on images
|
|
340
|
+
- Use skeleton loaders that match final content dimensions
|
|
341
|
+
- Reserve space for dynamic content
|
|
342
|
+
|
|
343
|
+
### Resource Loading
|
|
344
|
+
- Preconnect to asset domains
|
|
345
|
+
- Preload critical fonts
|
|
346
|
+
- Move expensive computation to Web Workers
|
|
347
|
+
|
|
348
|
+
### {{styling}} Tips
|
|
349
|
+
- Use `h-dvh` instead of `h-screen` (handles mobile browser chrome)
|
|
350
|
+
- Use `size-*` for square elements (e.g., `size-10` = `w-10 h-10`)
|
|
351
|
+
- Maintain a fixed z-index scale (avoid z-index wars)
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Visual Polish
|
|
356
|
+
|
|
357
|
+
### Shadows
|
|
358
|
+
Use layered shadows for depth (ambient + direct light):
|
|
359
|
+
```css
|
|
360
|
+
/* Subtle elevation */
|
|
361
|
+
box-shadow:
|
|
362
|
+
0 1px 2px rgba(0,0,0,0.05), /* ambient */
|
|
363
|
+
0 1px 3px rgba(0,0,0,0.1); /* direct */
|
|
364
|
+
|
|
365
|
+
/* Card elevation */
|
|
366
|
+
box-shadow:
|
|
367
|
+
0 2px 4px rgba(0,0,0,0.05),
|
|
368
|
+
0 4px 12px rgba(0,0,0,0.1);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Border Radius
|
|
372
|
+
Nested elements should have smaller radii:
|
|
373
|
+
```tsx
|
|
374
|
+
// Parent has larger radius
|
|
375
|
+
<Card className="rounded-xl p-4">
|
|
376
|
+
{/* Child radius <= parent radius minus padding */}
|
|
377
|
+
<div className="rounded-lg">...</div>
|
|
378
|
+
</Card>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Optical Alignment
|
|
382
|
+
Sometimes pixel-perfect isn't visually perfect:
|
|
383
|
+
- Adjust +/-1px when perception beats geometry
|
|
384
|
+
- Icons often need slight adjustments to appear centered
|
|
385
|
+
- Text baselines may need manual tweaking
|
|
386
|
+
|
|
387
|
+
### Design for All Data States
|
|
388
|
+
Always design for:
|
|
389
|
+
- **Empty**: No data yet (first-time user)
|
|
390
|
+
- **Sparse**: Just a few items
|
|
391
|
+
- **Dense**: Lots of data (test with 100+ items)
|
|
392
|
+
- **Error**: Something went wrong
|
|
393
|
+
|
|
394
|
+
### Typography Details
|
|
395
|
+
- Use tabular numbers for data comparisons (`font-variant-numeric: tabular-nums`)
|
|
396
|
+
- Use proper ellipsis character (`...`) not three dots
|
|
397
|
+
- Use typographic quotes (`"` `"`) in content
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Quality Checklist
|
|
402
|
+
|
|
403
|
+
Run before committing UI changes:
|
|
404
|
+
|
|
405
|
+
### Design Tokens
|
|
406
|
+
- [ ] No hard-coded colors (no `#fff`, `rgb()`, raw hex)
|
|
407
|
+
- [ ] Using {{styling}} classes or CSS variables
|
|
408
|
+
- [ ] Colors match light/dark theme
|
|
409
|
+
|
|
410
|
+
### Interaction States
|
|
411
|
+
- [ ] Hover state on all clickable elements
|
|
412
|
+
- [ ] Focus ring visible (keyboard navigation)
|
|
413
|
+
- [ ] Disabled state prevents interaction
|
|
414
|
+
- [ ] Loading state shows spinner/skeleton
|
|
415
|
+
|
|
416
|
+
### Responsive
|
|
417
|
+
- [ ] Tested at 375px width (mobile)
|
|
418
|
+
- [ ] No horizontal scroll on mobile
|
|
419
|
+
- [ ] Touch targets are 44px minimum
|
|
420
|
+
- [ ] Text readable without zoom
|
|
421
|
+
|
|
422
|
+
### States Handled
|
|
423
|
+
- [ ] Empty state is helpful (not blank)
|
|
424
|
+
- [ ] Loading state is visible
|
|
425
|
+
- [ ] Error state is styled and actionable
|
|
426
|
+
|
|
427
|
+
### Charts (if applicable)
|
|
428
|
+
- [ ] Has title describing the data
|
|
429
|
+
- [ ] Has tooltips on hover
|
|
430
|
+
- [ ] Has legend if multiple series
|
|
431
|
+
- [ ] Uses ChartContainer pattern
|
|
432
|
+
- [ ] Colors use chart tokens
|
|
433
|
+
|
|
434
|
+
### Accessibility
|
|
435
|
+
- [ ] Labels on all form inputs
|
|
436
|
+
- [ ] Alt text on images
|
|
437
|
+
- [ ] `aria-label` on icon-only buttons
|
|
438
|
+
- [ ] Color is not the only indicator
|
|
439
|
+
- [ ] Can navigate with keyboard
|
|
440
|
+
- [ ] Focus ring visible (`:focus-visible`)
|
|
441
|
+
|
|
442
|
+
### Forms
|
|
443
|
+
- [ ] Enter submits single-input forms
|
|
444
|
+
- [ ] Errors shown next to fields
|
|
445
|
+
- [ ] First error focused on submit
|
|
446
|
+
- [ ] Paste not blocked
|
|
447
|
+
- [ ] AlertDialog for destructive actions
|
|
448
|
+
|
|
449
|
+
### Performance
|
|
450
|
+
- [ ] Images have explicit dimensions
|
|
451
|
+
- [ ] Large lists virtualized
|
|
452
|
+
- [ ] Animations use transform/opacity only
|
|
453
|
+
- [ ] `prefers-reduced-motion` respected
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## When to Invoke `frontend-design` Skill
|
|
458
|
+
|
|
459
|
+
Use the `/frontend-design` skill for:
|
|
460
|
+
- New pages or dashboards
|
|
461
|
+
- Marketing or landing pages
|
|
462
|
+
- Complex data visualizations
|
|
463
|
+
- Features where distinctive aesthetics matter
|
|
464
|
+
|
|
465
|
+
The skill provides creative direction beyond these patterns - use it when you need bold, distinctive design, not just functional UI.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## Quick Reference
|
|
470
|
+
|
|
471
|
+
### Spacing Scale
|
|
472
|
+
```
|
|
473
|
+
0.5 = 2px 4 = 16px 10 = 40px
|
|
474
|
+
1 = 4px 5 = 20px 12 = 48px
|
|
475
|
+
2 = 8px 6 = 24px 16 = 64px
|
|
476
|
+
3 = 12px 8 = 32px 20 = 80px
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Common Patterns
|
|
480
|
+
```tsx
|
|
481
|
+
// Card with stats
|
|
482
|
+
<Card>
|
|
483
|
+
<CardHeader>
|
|
484
|
+
<CardTitle>Total Responses</CardTitle>
|
|
485
|
+
</CardHeader>
|
|
486
|
+
<CardContent>
|
|
487
|
+
<div className="text-3xl font-bold">1,234</div>
|
|
488
|
+
<p className="text-sm text-muted-foreground">+12% from last week</p>
|
|
489
|
+
</CardContent>
|
|
490
|
+
</Card>
|
|
491
|
+
|
|
492
|
+
// Form field with validation
|
|
493
|
+
<div className="space-y-2">
|
|
494
|
+
<Label htmlFor="email">Email</Label>
|
|
495
|
+
<Input id="email" type="email" {...register('email')} />
|
|
496
|
+
{errors.email && (
|
|
497
|
+
<p className="text-sm text-destructive">{errors.email.message}</p>
|
|
498
|
+
)}
|
|
499
|
+
</div>
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Color Tokens
|
|
503
|
+
```
|
|
504
|
+
background / foreground - page background and text
|
|
505
|
+
card / card-foreground - elevated surfaces
|
|
506
|
+
primary / primary-foreground - brand actions
|
|
507
|
+
secondary / secondary-foreground - secondary actions
|
|
508
|
+
muted / muted-foreground - subtle backgrounds/text
|
|
509
|
+
accent / accent-foreground - highlights
|
|
510
|
+
destructive / destructive-foreground - errors, danger
|
|
511
|
+
border - subtle borders
|
|
512
|
+
input - form input borders
|
|
513
|
+
ring - focus rings
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## References
|
|
519
|
+
|
|
520
|
+
Guidelines informed by:
|
|
521
|
+
- [Vercel Web Interface Guidelines](https://vercel.com/design/guidelines)
|
|
522
|
+
- [UI Skills](https://www.ui-skills.com) - Opinionated constraints for AI-assisted UI
|
|
523
|
+
- [/rams](https://www.rams.ai) - Design review framework (WCAG, visual quality)
|