@lifeonlars/prime-yggdrasil 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 +30 -0
- package/README.md +276 -0
- package/dist/foundations.css +180 -0
- package/dist/index.cjs +1 -0
- package/dist/index.js +11 -0
- package/dist/vite.svg +1 -0
- package/dist/yggdrasil-dark.css +12 -0
- package/dist/yggdrasil-light.css +12 -0
- package/docs/AI-AGENT-GUIDE.md +575 -0
- package/docs/CONSUMPTION-GUIDE.md +384 -0
- package/docs/ELEVATION-IMPLEMENTATION.md +146 -0
- package/docs/ELEVATION-SYSTEM.md +104 -0
- package/docs/NPM-PUBLISHING-GUIDE.md +337 -0
- package/docs/PACKAGING-CHECKLIST.md +193 -0
- package/docs/PRE-PUBLISH-CHECKLIST.md +136 -0
- package/docs/README.md +161 -0
- package/docs/archive/README.md +27 -0
- package/docs/archive/SEMANTIC-MIGRATION-PLAN.md +177 -0
- package/docs/archive/YGGDRASIL_THEME.md +264 -0
- package/docs/archive/agentic_policy.md +216 -0
- package/docs/contrast-report.md +9 -0
- package/docs/scripts/README.md +180 -0
- package/package.json +113 -0
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
# Yggdrasil Design System - AI Agent Guide
|
|
2
|
+
|
|
3
|
+
**Purpose**: This guide helps AI agents maintain design consistency and use component-driven development when building applications with the Yggdrasil design system.
|
|
4
|
+
|
|
5
|
+
## 🎯 Core Principles for Agents
|
|
6
|
+
|
|
7
|
+
### 1. **Always Reuse, Never Recreate**
|
|
8
|
+
- Use existing PrimeReact components
|
|
9
|
+
- Apply existing semantic tokens
|
|
10
|
+
- Reference existing patterns from Storybook
|
|
11
|
+
- Only create new components when PrimeReact doesn't provide equivalent functionality
|
|
12
|
+
|
|
13
|
+
### 2. **Design System First**
|
|
14
|
+
Before writing any UI code, **always**:
|
|
15
|
+
1. Check if PrimeReact has the component you need
|
|
16
|
+
2. Check Storybook for usage examples
|
|
17
|
+
3. Check semantic tokens for styling needs
|
|
18
|
+
4. Use the design system's spacing/sizing conventions
|
|
19
|
+
|
|
20
|
+
### 3. **Token-Based Styling Only**
|
|
21
|
+
- ❌ Never write: `color: #374151`
|
|
22
|
+
- ✅ Always write: `color: var(--text-neutral-default)`
|
|
23
|
+
- ❌ Never write: `border-radius: 6px`
|
|
24
|
+
- ✅ Always write: `border-radius: var(--radius-md)`
|
|
25
|
+
|
|
26
|
+
## 📚 Quick Reference for Common Tasks
|
|
27
|
+
|
|
28
|
+
### Choosing Colors
|
|
29
|
+
|
|
30
|
+
**For text:**
|
|
31
|
+
```css
|
|
32
|
+
--text-neutral-default /* Main body text (dark in light mode) */
|
|
33
|
+
--text-neutral-subdued /* Secondary/muted text */
|
|
34
|
+
--text-neutral-loud /* Emphasized text (extra dark) */
|
|
35
|
+
--text-neutral-disabled /* Disabled state text */
|
|
36
|
+
--text-state-interactive /* Interactive elements (links, buttons) */
|
|
37
|
+
--text-onsurface-onbrand /* Text on brand-colored backgrounds (white) */
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**For surfaces/backgrounds:**
|
|
41
|
+
```css
|
|
42
|
+
--surface-neutral-primary /* Main backgrounds (white in light mode) */
|
|
43
|
+
--surface-neutral-secondary /* Secondary backgrounds (light gray) */
|
|
44
|
+
--surface-neutral-tertiary /* Tertiary backgrounds (lighter gray) */
|
|
45
|
+
--surface-brand-primary /* Brand primary (main blue) */
|
|
46
|
+
--surface-state-hover /* Hover state background */
|
|
47
|
+
--surface-state-selected /* Selected state background */
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**For borders:**
|
|
51
|
+
```css
|
|
52
|
+
--border-neutral-default /* Standard borders */
|
|
53
|
+
--border-neutral-subdued /* Subtle borders (lighter) */
|
|
54
|
+
--border-state-interactive /* Interactive element borders */
|
|
55
|
+
--border-state-focus /* Focus rings */
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**For context/feedback:**
|
|
59
|
+
```css
|
|
60
|
+
/* Use severity tokens for messages, alerts, etc. */
|
|
61
|
+
--severity-info-surface /* Info background */
|
|
62
|
+
--severity-info-text /* Info text */
|
|
63
|
+
--severity-info-border /* Info border */
|
|
64
|
+
|
|
65
|
+
--severity-success-surface /* Success background */
|
|
66
|
+
--severity-danger-surface /* Danger/error background */
|
|
67
|
+
--severity-warn-surface /* Warning background */
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Choosing Spacing
|
|
71
|
+
|
|
72
|
+
**Always use the 4px grid:**
|
|
73
|
+
```css
|
|
74
|
+
/* ✅ CORRECT */
|
|
75
|
+
padding: 0.5rem; /* 8px */
|
|
76
|
+
padding: 1rem; /* 16px */
|
|
77
|
+
padding: 1.5rem; /* 24px */
|
|
78
|
+
margin: 2rem; /* 32px */
|
|
79
|
+
|
|
80
|
+
/* ❌ INCORRECT */
|
|
81
|
+
padding: 10px; /* Not on 4px grid */
|
|
82
|
+
margin: 15px; /* Not on 4px grid */
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Common spacing values:**
|
|
86
|
+
- `0.25rem` (4px) - Minimal spacing
|
|
87
|
+
- `0.5rem` (8px) - Tight spacing
|
|
88
|
+
- `0.75rem` (12px) - Compact spacing
|
|
89
|
+
- `1rem` (16px) - Standard spacing
|
|
90
|
+
- `1.25rem` (20px) - Comfortable spacing
|
|
91
|
+
- `1.5rem` (24px) - Spacious
|
|
92
|
+
- `2rem` (32px) - Large gaps
|
|
93
|
+
|
|
94
|
+
### Choosing Border Radius
|
|
95
|
+
|
|
96
|
+
```css
|
|
97
|
+
--radius-sm /* 4px - Subtle rounding */
|
|
98
|
+
--radius-md /* 8px - Standard (buttons, inputs) */
|
|
99
|
+
--radius-lg /* 12px - Cards, panels */
|
|
100
|
+
--radius-xl /* 16px - Large containers */
|
|
101
|
+
--radius-full /* 9999px - Pills, avatars */
|
|
102
|
+
|
|
103
|
+
/* Component-specific */
|
|
104
|
+
--button-radius /* Buttons (8px) */
|
|
105
|
+
--input-radius /* Form inputs (8px) */
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Choosing Elevation/Shadows
|
|
109
|
+
|
|
110
|
+
```css
|
|
111
|
+
--elevation-subtle /* Minimal depth (tooltips) */
|
|
112
|
+
--elevation-moderate /* Standard depth (dropdowns, cards) */
|
|
113
|
+
--elevation-elevated /* Significant depth (modals) */
|
|
114
|
+
--elevation-high /* Maximum depth (drawers) */
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Or use utility classes:
|
|
118
|
+
```jsx
|
|
119
|
+
<div className="shadow-1">Subtle shadow</div>
|
|
120
|
+
<div className="shadow-2">Moderate shadow</div>
|
|
121
|
+
<div className="shadow-3">Elevated shadow</div>
|
|
122
|
+
<div className="shadow-4">High shadow</div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 🧩 Component Selection Guide
|
|
126
|
+
|
|
127
|
+
### Data Display
|
|
128
|
+
|
|
129
|
+
**Instead of creating tables:**
|
|
130
|
+
```tsx
|
|
131
|
+
import { DataTable } from 'primereact/datatable';
|
|
132
|
+
import { Column } from 'primereact/column';
|
|
133
|
+
|
|
134
|
+
<DataTable value={data}>
|
|
135
|
+
<Column field="name" header="Name" />
|
|
136
|
+
<Column field="email" header="Email" />
|
|
137
|
+
</DataTable>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Forms
|
|
141
|
+
|
|
142
|
+
**Instead of creating inputs:**
|
|
143
|
+
```tsx
|
|
144
|
+
import { InputText } from 'primereact/inputtext';
|
|
145
|
+
import { Dropdown } from 'primereact/dropdown';
|
|
146
|
+
import { Calendar } from 'primereact/calendar';
|
|
147
|
+
|
|
148
|
+
<InputText placeholder="Enter text" />
|
|
149
|
+
<Dropdown options={items} />
|
|
150
|
+
<Calendar showTime />
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Buttons
|
|
154
|
+
|
|
155
|
+
**Yggdrasil supports these button variants:**
|
|
156
|
+
```tsx
|
|
157
|
+
import { Button } from 'primereact/button';
|
|
158
|
+
|
|
159
|
+
{/* Primary - main actions */}
|
|
160
|
+
<Button label="Save" />
|
|
161
|
+
|
|
162
|
+
{/* Outlined - secondary actions */}
|
|
163
|
+
<Button label="Cancel" outlined />
|
|
164
|
+
|
|
165
|
+
{/* Link/Text - tertiary actions */}
|
|
166
|
+
<Button label="Learn More" text />
|
|
167
|
+
|
|
168
|
+
{/* Danger - destructive actions */}
|
|
169
|
+
<Button label="Delete" severity="danger" />
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**❌ Don't use:** `secondary`, `help`, `contrast`, `info`, `success`, `warning` buttons (removed from design system)
|
|
173
|
+
|
|
174
|
+
### Navigation
|
|
175
|
+
|
|
176
|
+
**Instead of creating menus:**
|
|
177
|
+
```tsx
|
|
178
|
+
import { Menubar } from 'primereact/menubar';
|
|
179
|
+
import { Breadcrumb } from 'primereact/breadcrumb';
|
|
180
|
+
import { Steps } from 'primereact/steps';
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Feedback
|
|
184
|
+
|
|
185
|
+
**Instead of creating alerts:**
|
|
186
|
+
```tsx
|
|
187
|
+
import { Message } from 'primereact/message';
|
|
188
|
+
import { Toast } from 'primereact/toast';
|
|
189
|
+
|
|
190
|
+
<Message severity="info" text="Information message" />
|
|
191
|
+
<Message severity="success" text="Success message" />
|
|
192
|
+
<Message severity="warn" text="Warning message" />
|
|
193
|
+
<Message severity="error" text="Error message" />
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 🚫 Common Mistakes to Avoid
|
|
197
|
+
|
|
198
|
+
### 1. Creating Bespoke Components
|
|
199
|
+
```tsx
|
|
200
|
+
// ❌ DON'T DO THIS
|
|
201
|
+
const CustomButton = ({ children }) => (
|
|
202
|
+
<button style={{
|
|
203
|
+
background: '#3B82F6',
|
|
204
|
+
color: 'white',
|
|
205
|
+
padding: '10px 20px',
|
|
206
|
+
borderRadius: '6px'
|
|
207
|
+
}}>
|
|
208
|
+
{children}
|
|
209
|
+
</button>
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// ✅ DO THIS INSTEAD
|
|
213
|
+
import { Button } from 'primereact/button';
|
|
214
|
+
<Button label={children} />
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 2. Using Hardcoded Colors
|
|
218
|
+
```tsx
|
|
219
|
+
// ❌ DON'T DO THIS
|
|
220
|
+
<div style={{ color: '#374151', background: '#F9FAFB' }}>
|
|
221
|
+
|
|
222
|
+
// ✅ DO THIS INSTEAD
|
|
223
|
+
<div style={{
|
|
224
|
+
color: 'var(--text-neutral-default)',
|
|
225
|
+
background: 'var(--surface-neutral-secondary)'
|
|
226
|
+
}}>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 3. Breaking the 4px Grid
|
|
230
|
+
```tsx
|
|
231
|
+
// ❌ DON'T DO THIS
|
|
232
|
+
<div style={{ padding: '15px', margin: '10px' }}>
|
|
233
|
+
|
|
234
|
+
// ✅ DO THIS INSTEAD
|
|
235
|
+
<div style={{ padding: '1rem', margin: '0.75rem' }}> {/* 16px, 12px */}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 4. Ignoring Existing Patterns
|
|
239
|
+
```tsx
|
|
240
|
+
// ❌ DON'T DO THIS - Creating custom card
|
|
241
|
+
<div className="my-custom-card" style={{ border: '1px solid #ccc' }}>
|
|
242
|
+
|
|
243
|
+
// ✅ DO THIS INSTEAD - Use PrimeReact Card
|
|
244
|
+
import { Card } from 'primereact/card';
|
|
245
|
+
<Card>Content</Card>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## 🔍 Decision Tree for UI Development
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
Need to add UI element?
|
|
252
|
+
│
|
|
253
|
+
├─ Does PrimeReact have this component?
|
|
254
|
+
│ ├─ YES → Use PrimeReact component
|
|
255
|
+
│ │ Check Storybook for examples
|
|
256
|
+
│ │ Apply semantic tokens if custom styling needed
|
|
257
|
+
│ │
|
|
258
|
+
│ └─ NO → Is this a simple layout/container?
|
|
259
|
+
│ ├─ YES → Use semantic tokens with basic HTML/divs
|
|
260
|
+
│ │ Follow 4px grid, use token-based styling
|
|
261
|
+
│ │
|
|
262
|
+
│ └─ NO → Check if combination of PrimeReact components works
|
|
263
|
+
│ ├─ YES → Compose PrimeReact components
|
|
264
|
+
│ └─ NO → Create new component (rare!)
|
|
265
|
+
│ Document in Storybook
|
|
266
|
+
│ Use semantic tokens exclusively
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## 📦 Packaging for Consumption
|
|
270
|
+
|
|
271
|
+
When integrating Yggdrasil into another project:
|
|
272
|
+
|
|
273
|
+
### 1. Installation
|
|
274
|
+
```bash
|
|
275
|
+
npm install prime-yggdrasil
|
|
276
|
+
npm install primereact primeicons
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### 2. Import Theme
|
|
280
|
+
```tsx
|
|
281
|
+
// In your main app file
|
|
282
|
+
import 'prime-yggdrasil/yggdrasil-light.css'; // or yggdrasil-dark.css
|
|
283
|
+
import 'primeicons/primeicons.css';
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 3. Use Components
|
|
287
|
+
```tsx
|
|
288
|
+
import { Button } from 'primereact/button';
|
|
289
|
+
import { DataTable } from 'primereact/datatable';
|
|
290
|
+
|
|
291
|
+
function App() {
|
|
292
|
+
return (
|
|
293
|
+
<div style={{ color: 'var(--text-neutral-default)' }}>
|
|
294
|
+
<Button label="Click me" />
|
|
295
|
+
</div>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 🎨 Storybook Reference
|
|
301
|
+
|
|
302
|
+
Before creating any component, **always check Storybook first**:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
npm run dev # Starts Storybook on localhost:6006
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Key Storybook sections:**
|
|
309
|
+
- **Design System** - Colors, Elevation, Severity (reference for tokens)
|
|
310
|
+
- **Components** - All PrimeReact components with examples
|
|
311
|
+
- **Blocks** - Custom composite components (if any)
|
|
312
|
+
|
|
313
|
+
## 🤖 AI-Specific Workflow
|
|
314
|
+
|
|
315
|
+
### Step 1: Understand the Request
|
|
316
|
+
```
|
|
317
|
+
User asks: "Add a form with name, email, and submit button"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Step 2: Check Design System
|
|
321
|
+
- Form inputs? → PrimeReact InputText
|
|
322
|
+
- Button? → PrimeReact Button
|
|
323
|
+
- Layout? → Standard HTML + semantic tokens
|
|
324
|
+
|
|
325
|
+
### Step 3: Reference Storybook
|
|
326
|
+
- Check InputText examples in Storybook
|
|
327
|
+
- Check Button examples in Storybook
|
|
328
|
+
- Note any specific patterns (labels, validation, etc.)
|
|
329
|
+
|
|
330
|
+
### Step 4: Implement with Tokens
|
|
331
|
+
```tsx
|
|
332
|
+
import { InputText } from 'primereact/inputtext';
|
|
333
|
+
import { Button } from 'primereact/button';
|
|
334
|
+
|
|
335
|
+
<div style={{
|
|
336
|
+
display: 'flex',
|
|
337
|
+
flexDirection: 'column',
|
|
338
|
+
gap: '1rem', // 16px on 4px grid
|
|
339
|
+
padding: '1.5rem' // 24px on 4px grid
|
|
340
|
+
}}>
|
|
341
|
+
<label style={{ color: 'var(--text-neutral-default)' }}>
|
|
342
|
+
Name
|
|
343
|
+
<InputText style={{ width: '100%' }} />
|
|
344
|
+
</label>
|
|
345
|
+
|
|
346
|
+
<label style={{ color: 'var(--text-neutral-default)' }}>
|
|
347
|
+
Email
|
|
348
|
+
<InputText type="email" style={{ width: '100%' }} />
|
|
349
|
+
</label>
|
|
350
|
+
|
|
351
|
+
<Button label="Submit" />
|
|
352
|
+
</div>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Step 5: Verify
|
|
356
|
+
- All colors use semantic tokens? ✓
|
|
357
|
+
- All spacing on 4px grid? ✓
|
|
358
|
+
- Using PrimeReact components? ✓
|
|
359
|
+
- Matches Storybook patterns? ✓
|
|
360
|
+
|
|
361
|
+
## 📋 Pre-Implementation Checklist
|
|
362
|
+
|
|
363
|
+
Before writing any UI code, verify:
|
|
364
|
+
|
|
365
|
+
- [ ] Checked PrimeReact documentation for existing component
|
|
366
|
+
- [ ] Reviewed Storybook for usage examples
|
|
367
|
+
- [ ] Identified semantic tokens needed
|
|
368
|
+
- [ ] Confirmed spacing follows 4px grid
|
|
369
|
+
- [ ] No hardcoded colors or sizes in implementation
|
|
370
|
+
- [ ] Component will work in both light and dark modes
|
|
371
|
+
|
|
372
|
+
## 📖 PrimeReact Component Reference
|
|
373
|
+
|
|
374
|
+
Before implementing any UI, **always check PrimeReact documentation first**:
|
|
375
|
+
|
|
376
|
+
### Core Component Categories
|
|
377
|
+
|
|
378
|
+
**Form Components**: https://primereact.org/inputtext/
|
|
379
|
+
- InputText, InputNumber, InputMask, InputTextarea
|
|
380
|
+
- Dropdown, MultiSelect, AutoComplete, TreeSelect
|
|
381
|
+
- Calendar, ColorPicker, Slider, Knob
|
|
382
|
+
- Checkbox, RadioButton, ToggleButton, SelectButton
|
|
383
|
+
- FileUpload, Password, Rating
|
|
384
|
+
|
|
385
|
+
**Data Display**: https://primereact.org/datatable/
|
|
386
|
+
- DataTable (sortable, filterable, paginated tables)
|
|
387
|
+
- TreeTable (hierarchical data)
|
|
388
|
+
- DataView (flexible data display)
|
|
389
|
+
- Timeline, OrderList, PickList
|
|
390
|
+
|
|
391
|
+
**Panels & Containers**: https://primereact.org/panel/
|
|
392
|
+
- Panel, Fieldset, Card, Accordion
|
|
393
|
+
- TabView, Splitter, ScrollPanel
|
|
394
|
+
- Toolbar, Divider
|
|
395
|
+
|
|
396
|
+
**Overlays**: https://primereact.org/dialog/
|
|
397
|
+
- Dialog, Sidebar, Drawer
|
|
398
|
+
- OverlayPanel, ConfirmDialog, ConfirmPopup
|
|
399
|
+
- Tooltip
|
|
400
|
+
|
|
401
|
+
**Navigation**: https://primereact.org/menubar/
|
|
402
|
+
- Menubar, Menu, TieredMenu, MegaMenu
|
|
403
|
+
- Breadcrumb, Steps, TabMenu
|
|
404
|
+
- PanelMenu, ContextMenu
|
|
405
|
+
|
|
406
|
+
**Messages**: https://primereact.org/message/
|
|
407
|
+
- Message, Messages, Toast
|
|
408
|
+
- InlineMessage
|
|
409
|
+
|
|
410
|
+
**Buttons**: https://primereact.org/button/
|
|
411
|
+
- Button, SplitButton, SpeedDial
|
|
412
|
+
|
|
413
|
+
**Media**: https://primereact.org/image/
|
|
414
|
+
- Image, Galleria, Carousel
|
|
415
|
+
|
|
416
|
+
### How to Use PrimeReact Docs
|
|
417
|
+
|
|
418
|
+
1. **Search by use case**: "I need a dropdown" → Search "dropdown"
|
|
419
|
+
2. **Check API tab**: See all available props and events
|
|
420
|
+
3. **View examples**: Copy working code snippets
|
|
421
|
+
4. **Adapt with tokens**: Replace any inline styles with semantic tokens
|
|
422
|
+
|
|
423
|
+
Example workflow:
|
|
424
|
+
```
|
|
425
|
+
Need: Date picker
|
|
426
|
+
1. Visit: https://primereact.org/calendar/
|
|
427
|
+
2. Copy: Basic example code
|
|
428
|
+
3. Adapt: Add semantic token styling if needed
|
|
429
|
+
4. Test: In both light and dark modes
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
## 🏗️ Creating Local Blocks (Project-Specific)
|
|
433
|
+
|
|
434
|
+
Sometimes you need composite components specific to your project. These are called "blocks" (inspired by PrimeBlocks).
|
|
435
|
+
|
|
436
|
+
### When to Create a Local Block
|
|
437
|
+
|
|
438
|
+
✅ **Create a local block when:**
|
|
439
|
+
- Combining multiple PrimeReact components into a project-specific pattern
|
|
440
|
+
- Building a complex layout that's reused multiple times in YOUR project
|
|
441
|
+
- Creating domain-specific composites (e.g., "UserProfileCard", "OrderSummaryPanel")
|
|
442
|
+
|
|
443
|
+
❌ **Don't create a local block when:**
|
|
444
|
+
- A single PrimeReact component would suffice
|
|
445
|
+
- The pattern is only used once
|
|
446
|
+
- It duplicates existing PrimeReact functionality
|
|
447
|
+
|
|
448
|
+
### Local Block Guidelines
|
|
449
|
+
|
|
450
|
+
**Location**: Create blocks in your project, NOT in the design system
|
|
451
|
+
```
|
|
452
|
+
your-project/
|
|
453
|
+
├── src/
|
|
454
|
+
│ ├── blocks/ # Your project-specific blocks
|
|
455
|
+
│ │ ├── UserCard.tsx
|
|
456
|
+
│ │ ├── StatsDashboard.tsx
|
|
457
|
+
│ │ └── CheckoutForm.tsx
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Rules for blocks:**
|
|
461
|
+
1. **Use only PrimeReact components** - Don't create custom base components
|
|
462
|
+
2. **Use only semantic tokens** - No hardcoded colors or spacing
|
|
463
|
+
3. **Follow 4px grid** - All spacing must follow the grid
|
|
464
|
+
4. **Make them generic** - Can be reused across your project
|
|
465
|
+
5. **Document in your project** - Add to your local Storybook
|
|
466
|
+
|
|
467
|
+
**Example: Good Local Block**
|
|
468
|
+
```tsx
|
|
469
|
+
// src/blocks/UserCard.tsx
|
|
470
|
+
import { Card } from 'primereact/card';
|
|
471
|
+
import { Button } from 'primereact/button';
|
|
472
|
+
import { Avatar } from 'primereact/avatar';
|
|
473
|
+
|
|
474
|
+
interface UserCardProps {
|
|
475
|
+
name: string;
|
|
476
|
+
email: string;
|
|
477
|
+
avatar?: string;
|
|
478
|
+
onContact: () => void;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function UserCard({ name, email, avatar, onContact }: UserCardProps) {
|
|
482
|
+
return (
|
|
483
|
+
<Card
|
|
484
|
+
style={{
|
|
485
|
+
padding: '1.5rem', // 24px - 4px grid
|
|
486
|
+
borderRadius: 'var(--radius-lg)',
|
|
487
|
+
background: 'var(--surface-neutral-primary)',
|
|
488
|
+
color: 'var(--text-neutral-default)'
|
|
489
|
+
}}
|
|
490
|
+
>
|
|
491
|
+
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
|
492
|
+
<Avatar
|
|
493
|
+
image={avatar}
|
|
494
|
+
label={!avatar ? name[0] : undefined}
|
|
495
|
+
size="large"
|
|
496
|
+
shape="circle"
|
|
497
|
+
/>
|
|
498
|
+
<div style={{ flex: 1 }}>
|
|
499
|
+
<h3 style={{
|
|
500
|
+
margin: 0,
|
|
501
|
+
color: 'var(--text-neutral-loud)'
|
|
502
|
+
}}>
|
|
503
|
+
{name}
|
|
504
|
+
</h3>
|
|
505
|
+
<p style={{
|
|
506
|
+
margin: '0.25rem 0 0',
|
|
507
|
+
color: 'var(--text-neutral-subdued)'
|
|
508
|
+
}}>
|
|
509
|
+
{email}
|
|
510
|
+
</p>
|
|
511
|
+
</div>
|
|
512
|
+
<Button
|
|
513
|
+
label="Contact"
|
|
514
|
+
icon="pi pi-envelope"
|
|
515
|
+
onClick={onContact}
|
|
516
|
+
/>
|
|
517
|
+
</div>
|
|
518
|
+
</Card>
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**Example: Bad Local Block (Don't do this)**
|
|
524
|
+
```tsx
|
|
525
|
+
// ❌ DON'T DO THIS
|
|
526
|
+
export function UserCard({ name, email }: Props) {
|
|
527
|
+
return (
|
|
528
|
+
// Creating custom card instead of using PrimeReact
|
|
529
|
+
<div style={{
|
|
530
|
+
background: '#ffffff', // ❌ Hardcoded color
|
|
531
|
+
border: '1px solid #e5e7eb', // ❌ Hardcoded color
|
|
532
|
+
borderRadius: '6px', // ❌ Not on 4px grid
|
|
533
|
+
padding: '15px' // ❌ Not on 4px grid
|
|
534
|
+
}}>
|
|
535
|
+
{/* Custom button instead of PrimeReact */}
|
|
536
|
+
<button style={{ background: '#3B82F6' }}> {/* ❌ Custom component */}
|
|
537
|
+
Contact
|
|
538
|
+
</button>
|
|
539
|
+
</div>
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### When to Promote Blocks to Design System
|
|
545
|
+
|
|
546
|
+
If you find a block being used across **multiple projects**, consider promoting it to the design system:
|
|
547
|
+
|
|
548
|
+
1. **Document the use case** - Why is this needed across projects?
|
|
549
|
+
2. **Generalize the API** - Make it work for broader use cases
|
|
550
|
+
3. **Add to design system** - Submit PR with Storybook documentation
|
|
551
|
+
4. **Test thoroughly** - Ensure it works in all contexts
|
|
552
|
+
5. **Update AI guide** - Add to component reference
|
|
553
|
+
|
|
554
|
+
## 🎓 Learning Resources
|
|
555
|
+
|
|
556
|
+
1. **PrimeReact Docs**: https://primereact.org/ (comprehensive component reference)
|
|
557
|
+
2. **PrimeReact Showcase**: https://primereact.org/installation/ (live examples)
|
|
558
|
+
3. **PrimeReact GitHub**: https://github.com/primefaces/primereact (source code, issues)
|
|
559
|
+
4. **Local Storybook**: `npm run dev` → localhost:6006 (themed examples)
|
|
560
|
+
5. **Semantic Token Reference**: `src/theme/semantic-light.css` (all tokens)
|
|
561
|
+
6. **Component Examples**: `src/stories/` (usage patterns)
|
|
562
|
+
|
|
563
|
+
## 🚀 Success Metrics
|
|
564
|
+
|
|
565
|
+
Your implementation is successful when:
|
|
566
|
+
- ✅ Zero hardcoded colors (all use semantic tokens)
|
|
567
|
+
- ✅ Zero spacing values that break 4px grid
|
|
568
|
+
- ✅ Maximum reuse of PrimeReact components
|
|
569
|
+
- ✅ Works in both light and dark modes
|
|
570
|
+
- ✅ Matches Storybook examples and patterns
|
|
571
|
+
- ✅ No duplicate/bespoke components created
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
**Remember**: The goal is consistency through reuse, not creativity through reinvention. Every component you don't create is a maintenance burden you avoid.
|