ux-toolkit 0.1.0 → 0.4.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/README.md +113 -7
- package/agents/card-reviewer.md +173 -0
- package/agents/comparison-reviewer.md +143 -0
- package/agents/density-reviewer.md +207 -0
- package/agents/detail-page-reviewer.md +143 -0
- package/agents/editor-reviewer.md +165 -0
- package/agents/form-reviewer.md +156 -0
- package/agents/game-ui-reviewer.md +181 -0
- package/agents/list-page-reviewer.md +132 -0
- package/agents/navigation-reviewer.md +145 -0
- package/agents/panel-reviewer.md +182 -0
- package/agents/replay-reviewer.md +174 -0
- package/agents/settings-reviewer.md +166 -0
- package/agents/ux-auditor.md +145 -45
- package/agents/ux-engineer.md +211 -38
- package/dist/cli.js +172 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +172 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -4
- package/dist/index.d.ts +128 -4
- package/dist/index.js +172 -5
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/skills/canvas-grid-patterns/SKILL.md +367 -0
- package/skills/comparison-patterns/SKILL.md +354 -0
- package/skills/data-density-patterns/SKILL.md +493 -0
- package/skills/detail-page-patterns/SKILL.md +522 -0
- package/skills/drag-drop-patterns/SKILL.md +406 -0
- package/skills/editor-workspace-patterns/SKILL.md +552 -0
- package/skills/event-timeline-patterns/SKILL.md +542 -0
- package/skills/form-patterns/SKILL.md +608 -0
- package/skills/info-card-patterns/SKILL.md +531 -0
- package/skills/keyboard-shortcuts-patterns/SKILL.md +365 -0
- package/skills/list-page-patterns/SKILL.md +351 -0
- package/skills/modal-patterns/SKILL.md +750 -0
- package/skills/navigation-patterns/SKILL.md +476 -0
- package/skills/page-structure-patterns/SKILL.md +271 -0
- package/skills/playback-replay-patterns/SKILL.md +695 -0
- package/skills/react-ux-patterns/SKILL.md +434 -0
- package/skills/split-panel-patterns/SKILL.md +609 -0
- package/skills/status-visualization-patterns/SKILL.md +635 -0
- package/skills/toast-notification-patterns/SKILL.md +207 -0
- package/skills/turn-based-ui-patterns/SKILL.md +506 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: page-structure-patterns
|
|
3
|
+
description: Base requirements for page structure, states, and layout patterns that apply to ALL screens in React/Next.js applications
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Page Structure Base Requirements
|
|
8
|
+
|
|
9
|
+
Every screen in the application MUST follow these base patterns. This checklist applies regardless of page type.
|
|
10
|
+
|
|
11
|
+
## Page State Checklist
|
|
12
|
+
|
|
13
|
+
### Loading State ✓
|
|
14
|
+
Every page that fetches data MUST have a loading state.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// REQUIRED: Loading state component
|
|
18
|
+
if (isLoading) {
|
|
19
|
+
return <PageLoading message="Loading items..." />;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Standard PageLoading implementation
|
|
23
|
+
function PageLoading({ message = 'Loading...' }) {
|
|
24
|
+
return (
|
|
25
|
+
<div className="min-h-screen flex items-center justify-center bg-surface-deep">
|
|
26
|
+
<div className="text-center">
|
|
27
|
+
<div className="w-12 h-12 border-4 border-accent border-t-transparent rounded-full animate-spin mx-auto mb-4" />
|
|
28
|
+
<p className="text-text-secondary">{message}</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Error State ✓
|
|
36
|
+
Every page MUST handle error cases gracefully.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// REQUIRED: Error state with recovery path
|
|
40
|
+
if (error || !data) {
|
|
41
|
+
return (
|
|
42
|
+
<PageError
|
|
43
|
+
title="Item Not Found"
|
|
44
|
+
message={error || 'The requested item could not be found.'}
|
|
45
|
+
backLink="/items"
|
|
46
|
+
backLabel="Back to Items"
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Standard PageError implementation
|
|
52
|
+
function PageError({ title, message, backLink, backLabel = 'Go Back' }) {
|
|
53
|
+
return (
|
|
54
|
+
<div className="min-h-screen flex items-center justify-center p-8 bg-surface-deep">
|
|
55
|
+
<div className="bg-red-900/20 border border-red-600/30 rounded-xl p-8 max-w-md text-center">
|
|
56
|
+
<h2 className="text-xl font-semibold text-red-400 mb-2">{title}</h2>
|
|
57
|
+
<p className="text-text-secondary mb-6">{message}</p>
|
|
58
|
+
{backLink && (
|
|
59
|
+
<Link href={backLink} className="inline-block bg-surface-raised hover:bg-border text-white px-6 py-2 rounded-lg">
|
|
60
|
+
{backLabel}
|
|
61
|
+
</Link>
|
|
62
|
+
)}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Empty State ✓
|
|
70
|
+
Pages with lists/collections MUST show meaningful empty states.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// REQUIRED: Empty state with action
|
|
74
|
+
{items.length === 0 && (
|
|
75
|
+
<EmptyState
|
|
76
|
+
icon={<EmptyIcon className="w-16 h-16 text-text-muted" />}
|
|
77
|
+
title={hasFilters ? 'No items match your filters' : 'No items yet'}
|
|
78
|
+
message={hasFilters ? 'Try adjusting your search' : 'Create your first item to get started'}
|
|
79
|
+
action={!hasFilters && (
|
|
80
|
+
<Button variant="primary" onClick={handleCreate}>
|
|
81
|
+
Create First Item
|
|
82
|
+
</Button>
|
|
83
|
+
)}
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Page Layout Structure
|
|
89
|
+
|
|
90
|
+
### Standard Page Layout
|
|
91
|
+
EVERY page MUST use the consistent PageLayout wrapper.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// REQUIRED: Consistent page structure
|
|
95
|
+
return (
|
|
96
|
+
<PageLayout
|
|
97
|
+
title="Page Title" // REQUIRED
|
|
98
|
+
subtitle="Optional description" // Optional
|
|
99
|
+
backLink="/parent" // Required for detail pages
|
|
100
|
+
backLabel="Back to Parent" // Required if backLink provided
|
|
101
|
+
headerContent={<ActionButtons />} // Optional: Primary actions
|
|
102
|
+
maxWidth="default" // 'narrow' | 'default' | 'wide' | 'full'
|
|
103
|
+
>
|
|
104
|
+
{/* Page content */}
|
|
105
|
+
</PageLayout>
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Header Content Guidelines
|
|
110
|
+
| Page Type | Header Content |
|
|
111
|
+
|-----------|----------------|
|
|
112
|
+
| List Page | Create/Add button |
|
|
113
|
+
| Detail Page | Edit + Delete buttons |
|
|
114
|
+
| Create Page | None (actions in form) |
|
|
115
|
+
| Settings | None |
|
|
116
|
+
|
|
117
|
+
## Responsive Breakpoints
|
|
118
|
+
|
|
119
|
+
### Standard Breakpoints
|
|
120
|
+
```css
|
|
121
|
+
/* Mobile first */
|
|
122
|
+
sm: 640px /* Small tablets */
|
|
123
|
+
md: 768px /* Tablets */
|
|
124
|
+
lg: 1024px /* Desktop */
|
|
125
|
+
xl: 1280px /* Large desktop */
|
|
126
|
+
2xl: 1536px /* Extra large */
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Grid Patterns by Screen Size
|
|
130
|
+
```tsx
|
|
131
|
+
// List pages: Responsive grid
|
|
132
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
|
|
133
|
+
|
|
134
|
+
// Detail pages: Sidebar on desktop
|
|
135
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
136
|
+
<div className="lg:col-span-1">Sidebar</div>
|
|
137
|
+
<div className="lg:col-span-2">Main content</div>
|
|
138
|
+
</div>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Typography Hierarchy
|
|
142
|
+
|
|
143
|
+
### Required Text Classes
|
|
144
|
+
```
|
|
145
|
+
h1 (Page Title): text-3xl font-bold text-white
|
|
146
|
+
h2 (Section Title): text-lg font-semibold text-white
|
|
147
|
+
h3 (Card Title): text-base font-medium text-white
|
|
148
|
+
Body: text-sm text-text-primary
|
|
149
|
+
Secondary: text-sm text-text-secondary
|
|
150
|
+
Muted: text-xs text-text-muted
|
|
151
|
+
Mono/Data: font-mono text-sm
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Spacing System
|
|
155
|
+
|
|
156
|
+
### Consistent Spacing
|
|
157
|
+
```
|
|
158
|
+
Page padding: p-6
|
|
159
|
+
Card padding: p-5
|
|
160
|
+
Section gap: mb-6
|
|
161
|
+
Element gap: gap-4
|
|
162
|
+
Inline gap: gap-2
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Color Semantic Usage
|
|
166
|
+
|
|
167
|
+
### Required Color Mapping
|
|
168
|
+
| Usage | Color Class |
|
|
169
|
+
|-------|-------------|
|
|
170
|
+
| Primary actions | bg-accent, text-accent |
|
|
171
|
+
| Success states | text-emerald-400, bg-emerald-500/20 |
|
|
172
|
+
| Warning states | text-amber-400, bg-amber-500/20 |
|
|
173
|
+
| Error states | text-red-400, bg-red-500/20 |
|
|
174
|
+
| Info states | text-cyan-400, bg-cyan-500/20 |
|
|
175
|
+
| Muted/disabled | text-text-muted, opacity-50 |
|
|
176
|
+
|
|
177
|
+
## Accessibility Requirements
|
|
178
|
+
|
|
179
|
+
### ARIA Requirements
|
|
180
|
+
```tsx
|
|
181
|
+
// Loading states
|
|
182
|
+
<div role="status" aria-live="polite">Loading...</div>
|
|
183
|
+
|
|
184
|
+
// Error messages
|
|
185
|
+
<div role="alert">Error message</div>
|
|
186
|
+
|
|
187
|
+
// Interactive elements
|
|
188
|
+
<button aria-label="Delete item">
|
|
189
|
+
<TrashIcon />
|
|
190
|
+
</button>
|
|
191
|
+
|
|
192
|
+
// Form fields
|
|
193
|
+
<input
|
|
194
|
+
id="email"
|
|
195
|
+
aria-invalid={hasError}
|
|
196
|
+
aria-describedby={hasError ? 'email-error' : undefined}
|
|
197
|
+
/>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Keyboard Navigation
|
|
201
|
+
- All interactive elements must be focusable
|
|
202
|
+
- Tab order must be logical
|
|
203
|
+
- Escape closes modals/dropdowns
|
|
204
|
+
- Enter activates buttons/links
|
|
205
|
+
|
|
206
|
+
## Data Fetching Pattern
|
|
207
|
+
|
|
208
|
+
### Standard Data Loading
|
|
209
|
+
```tsx
|
|
210
|
+
function Page() {
|
|
211
|
+
const [data, setData] = useState(null);
|
|
212
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
213
|
+
const [error, setError] = useState(null);
|
|
214
|
+
|
|
215
|
+
useEffect(() => {
|
|
216
|
+
async function fetchData() {
|
|
217
|
+
try {
|
|
218
|
+
const response = await fetch('/api/items');
|
|
219
|
+
const result = await response.json();
|
|
220
|
+
if (result.success) {
|
|
221
|
+
setData(result.data);
|
|
222
|
+
} else {
|
|
223
|
+
setError(result.error || 'Failed to load');
|
|
224
|
+
}
|
|
225
|
+
} catch {
|
|
226
|
+
setError('Failed to connect to server');
|
|
227
|
+
} finally {
|
|
228
|
+
setIsLoading(false);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
fetchData();
|
|
232
|
+
}, []);
|
|
233
|
+
|
|
234
|
+
// REQUIRED: Handle all states
|
|
235
|
+
if (isLoading) return <PageLoading />;
|
|
236
|
+
if (error || !data) return <PageError message={error} />;
|
|
237
|
+
return <PageContent data={data} />;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Required Page Metadata
|
|
242
|
+
|
|
243
|
+
### Next.js Head
|
|
244
|
+
```tsx
|
|
245
|
+
// Every page should set appropriate title
|
|
246
|
+
<Head>
|
|
247
|
+
<title>{pageTitle} | AppName</title>
|
|
248
|
+
</Head>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Audit Checklist
|
|
252
|
+
|
|
253
|
+
When reviewing ANY page, verify:
|
|
254
|
+
|
|
255
|
+
### Critical (Must Fix)
|
|
256
|
+
- [ ] Has loading state - users see blank/broken page without it
|
|
257
|
+
- [ ] Has error state with recovery path - users get stuck without it
|
|
258
|
+
- [ ] Meets ARIA requirements - accessibility violation
|
|
259
|
+
- [ ] Keyboard navigable - accessibility violation
|
|
260
|
+
|
|
261
|
+
### Major (Should Fix)
|
|
262
|
+
- [ ] Has empty state (if applicable) - confusing without guidance
|
|
263
|
+
- [ ] Uses PageLayout wrapper - inconsistent experience
|
|
264
|
+
- [ ] Has appropriate title/subtitle - navigation confusion
|
|
265
|
+
- [ ] Has back navigation (if detail page) - users get trapped
|
|
266
|
+
- [ ] Responsive at all breakpoints - mobile users blocked
|
|
267
|
+
|
|
268
|
+
### Minor (Nice to Have)
|
|
269
|
+
- [ ] Header actions follow guidelines - consistency
|
|
270
|
+
- [ ] Follows typography hierarchy - visual polish
|
|
271
|
+
- [ ] Uses semantic colors correctly - visual polish
|