@vadimcomanescu/nadicode-design-system 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/seed/SKILL.md +38 -166
- package/.agents/skills/seed/references/animation.md +2 -2
- package/.agents/skills/seed/references/responsive.md +1 -1
- package/README.md +2 -2
- package/dist/catalog/components.js +4 -4
- package/dist/{chunk-7A2RXKGH.js → chunk-GJ557DGH.js} +1 -1
- package/dist/{chunk-7XLZCXUL.js → chunk-K4U67BVG.js} +1 -1
- package/dist/{chunk-TUJZMJXW.js → chunk-LK2L3C7D.js} +1 -1
- package/dist/{chunk-DSMGCFMJ.js → chunk-POFFOUQW.js} +2 -5
- package/dist/components/blocks/HeroBlock.js +2 -2
- package/dist/components/page-kits/LandingPageKit.js +3 -3
- package/dist/components/page-kits/ServiceSuitePageKit.js +3 -3
- package/dist/components/ui/AvatarUpload.js +1 -1
- package/dist/components/ui/MouseEffect.js +1 -1
- package/eslint-rules/nadicode/config.js +1 -0
- package/eslint-rules/nadicode/index.js +2 -0
- package/eslint-rules/nadicode/rules/__tests__/require-catalog-import.test.js +111 -0
- package/eslint-rules/nadicode/rules/no-has-svg-selector.js +1 -1
- package/eslint-rules/nadicode/rules/require-catalog-import.js +59 -0
- package/package.json +1 -338
- package/scripts/ds-check.mjs +0 -10
- package/scripts/sync-seed-skill.mjs +0 -3
- package/.agents/skills/seed/contract.md +0 -104
- package/.agents/skills/seed/intent-map.md +0 -320
- package/.agents/skills/seed/recipes/agency-home.md +0 -311
- package/.agents/skills/seed/recipes/agents-chat.md +0 -305
- package/.agents/skills/seed/recipes/analytics.md +0 -253
- package/.agents/skills/seed/recipes/auth.md +0 -254
- package/.agents/skills/seed/recipes/blog-content.md +0 -307
- package/.agents/skills/seed/recipes/checkout.md +0 -311
- package/.agents/skills/seed/recipes/company-about.md +0 -276
- package/.agents/skills/seed/recipes/company-contact.md +0 -234
- package/.agents/skills/seed/recipes/crud-form.md +0 -233
- package/.agents/skills/seed/recipes/crud-list-detail.md +0 -230
- package/.agents/skills/seed/recipes/dashboard.md +0 -354
- package/.agents/skills/seed/recipes/digital-workers.md +0 -314
- package/.agents/skills/seed/recipes/error-pages.md +0 -199
- package/.agents/skills/seed/recipes/marketing-landing.md +0 -293
- package/.agents/skills/seed/recipes/marketing-shell.md +0 -156
- package/.agents/skills/seed/recipes/navigation-shell.md +0 -786
- package/.agents/skills/seed/recipes/onboarding.md +0 -258
- package/.agents/skills/seed/recipes/pricing.md +0 -271
- package/.agents/skills/seed/recipes/service-detail.md +0 -302
- package/.agents/skills/seed/recipes/settings.md +0 -252
- package/.agents/skills/seed/references/blocks.md +0 -128
- package/.agents/skills/seed/references/components.md +0 -287
- package/.agents/skills/seed/references/icons.md +0 -169
- package/.agents/skills/seed/references/nextjs.md +0 -49
- package/.agents/skills/seed/references/tokens.md +0 -88
|
@@ -3,8 +3,8 @@ name: Seed Design System
|
|
|
3
3
|
description: >
|
|
4
4
|
Use when building UI with the Seed Design System or composing full pages from
|
|
5
5
|
Seed components. Covers tokens, components, glass effects, animations,
|
|
6
|
-
dual-axis theming, page
|
|
7
|
-
tags: [seed, design-system, arctic-glow, react, tailwind, radix, glassmorphism,
|
|
6
|
+
dual-axis theming, page-kits, and Next.js App Router integration.
|
|
7
|
+
tags: [seed, design-system, arctic-glow, react, tailwind, radix, glassmorphism, page-kits]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Seed Design System -- Agent Skill
|
|
@@ -20,7 +20,7 @@ Consumer scaffold contract: brand customization stays palette-only unless the ta
|
|
|
20
20
|
|
|
21
21
|
## Component Discovery
|
|
22
22
|
|
|
23
|
-
The catalog (`./catalog` and `./catalog/components` subpath exports) is the single surface for discovering and consuming Seed
|
|
23
|
+
The catalog (`./catalog` and `./catalog/components` subpath exports) is the single surface for discovering and consuming Seed blocks and page-kits.
|
|
24
24
|
|
|
25
25
|
**Discovery** (server-safe, read this to learn what's available):
|
|
26
26
|
```ts
|
|
@@ -36,61 +36,19 @@ import { seedComponents } from "@vadimcomanescu/nadicode-design-system/catalog/c
|
|
|
36
36
|
|
|
37
37
|
Usage:
|
|
38
38
|
```tsx
|
|
39
|
-
const { LoginBlock,
|
|
39
|
+
const { LoginBlock, DashboardPageKit } = seedComponents
|
|
40
40
|
<LoginBlock onSubmit={handleLogin} />
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
Do not import
|
|
43
|
+
**Blocks and page-kits** are imported exclusively from `seedComponents`. Do not import them via individual subpath exports (ADR 0009). The ESLint rule `nadicode/require-catalog-import` enforces this at lint time.
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
The derived references under `references/components.md` and `references/blocks.md` are generated from the catalog. Any repo `Path` column there is a maintainer source path, not a consumer import path.
|
|
45
|
+
**UI primitives** (Button, Heading, Input, etc.), icons, charts, and effects are imported via individual subpath exports. They are not registered in the catalog.
|
|
48
46
|
|
|
49
47
|
## Read Order
|
|
50
48
|
|
|
51
|
-
1. **This file** -- router, quick references, forbidden patterns
|
|
52
|
-
2.
|
|
53
|
-
3.
|
|
54
|
-
4. **`intent-map.md`** -- intent decision tree + recipe index
|
|
55
|
-
6. **`recipes/<page-type>.md`** -- matching recipe for your page
|
|
56
|
-
7. **`references/`** -- deep dives as needed
|
|
57
|
-
8. **`references/brand-override.md`** -- palette-only brand customization guide for seeded apps
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Intent Decision Tree
|
|
62
|
-
|
|
63
|
-
What are you building? Follow the tree to find your recipe.
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
Does user have a session?
|
|
67
|
-
YES --> app-shell intents:
|
|
68
|
-
dashboard .......... recipes/dashboard.md
|
|
69
|
-
CRUD list/detail ... recipes/crud-list-detail.md
|
|
70
|
-
CRUD form .......... recipes/crud-form.md
|
|
71
|
-
settings ........... recipes/settings.md
|
|
72
|
-
analytics .......... recipes/analytics.md
|
|
73
|
-
agents/chat ........ recipes/agents-chat.md
|
|
74
|
-
navigation shell ... recipes/navigation-shell.md
|
|
75
|
-
NO --> auth?
|
|
76
|
-
YES --> recipes/auth.md (auth-shell)
|
|
77
|
-
onboarding?
|
|
78
|
-
YES --> recipes/onboarding.md (onboarding-shell)
|
|
79
|
-
marketing intents (marketing-shell):
|
|
80
|
-
agency home ...... recipes/agency-home.md
|
|
81
|
-
landing .......... recipes/marketing-landing.md
|
|
82
|
-
digital workers .. recipes/digital-workers.md
|
|
83
|
-
service detail ... recipes/service-detail.md
|
|
84
|
-
pricing .......... recipes/pricing.md
|
|
85
|
-
blog/content ..... recipes/blog-content.md
|
|
86
|
-
about/team ....... recipes/company-about.md
|
|
87
|
-
contact .......... recipes/company-contact.md
|
|
88
|
-
checkout ......... recipes/checkout.md
|
|
89
|
-
marketing shell .. recipes/marketing-shell.md
|
|
90
|
-
error pages --> recipes/error-pages.md (fallback-shell)
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Full intent-to-recipe mapping with shell selection: see `intent-map.md`.
|
|
49
|
+
1. **This file** -- router, quick references, forbidden patterns, binary rules
|
|
50
|
+
2. **catalog** (`@vadimcomanescu/nadicode-design-system/catalog`) -- machine-readable component metadata (variants, props, tiers)
|
|
51
|
+
3. **`references/`** -- deep dives as needed
|
|
94
52
|
|
|
95
53
|
---
|
|
96
54
|
|
|
@@ -113,6 +71,28 @@ Full intent-to-recipe mapping with shell selection: see `intent-map.md`.
|
|
|
113
71
|
| CSS hex in vars: `--color-bg: #0F1114` | `--color-background: 15 17 20` | CSS vars use space-separated RGB |
|
|
114
72
|
| Block without `interface *Props` | `interface MyBlockProps { title?: string }` | Integrity test enforces |
|
|
115
73
|
| Required content props | Optional with defaults in destructuring | Blocks render standalone |
|
|
74
|
+
| Inline/floating labels | `Label` above control (stacked) | Form convention |
|
|
75
|
+
| `text-[10px]`, `text-[11px]` | `text-xs`, `text-sm`, `Heading`, `Typography` | No arbitrary text sizes |
|
|
76
|
+
| Ad-hoc `chat-*` classes | Compose Seed primitives + motion tokens | No custom chat classes |
|
|
77
|
+
| `import { BarChart } from "recharts"` | `import { BarChart } from "@vadimcomanescu/nadicode-design-system/charts"` | No direct recharts |
|
|
78
|
+
| Ad-hoc Card + value for KPIs | `MetricCard` | Use the DS component |
|
|
79
|
+
| Hex/rgb in chart config | `var(--color-chart-N)` tokens | Chart colors are tokenized |
|
|
80
|
+
| Generic English defaults | Override ALL default copy per brand | No shipping placeholder text |
|
|
81
|
+
| Hardcoded hex in components | Map to semantic tokens | Brand colors via tokens only |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Brand Customization
|
|
86
|
+
|
|
87
|
+
Override all default copy. Map brand colors to semantic tokens. Verify contrast (WCAG AA: 4.5:1 body, 3:1 large). See `references/brand-override.md` for glass intensity presets.
|
|
88
|
+
|
|
89
|
+
## Dashboard Rules
|
|
90
|
+
|
|
91
|
+
KPI cards: `MetricCard`. Charts: empty-data guard required (`data.length > 0`). Chart colors: `var(--color-chart-N)` tokens. Import from `./charts`, never `recharts` directly. Sidebar navigation must include IA grouping with `SidebarGroupLabel`.
|
|
92
|
+
|
|
93
|
+
## Admin Chat
|
|
94
|
+
|
|
95
|
+
Chat features must include all three agentic layers: Conversation, Tooling, Traceability. See catalog for available components in each layer. Analytics must use Seed chart primitives.
|
|
116
96
|
|
|
117
97
|
---
|
|
118
98
|
|
|
@@ -132,7 +112,7 @@ Full intent-to-recipe mapping with shell selection: see `intent-map.md`.
|
|
|
132
112
|
|
|
133
113
|
**Sidebar:** `sidebar`, `sidebar-foreground`, `sidebar-primary`, `sidebar-accent`, `sidebar-border`, `sidebar-ring`
|
|
134
114
|
|
|
135
|
-
|
|
115
|
+
Token source of truth: `src/lib/tokens.config.js` (authored), `src/index.css` (generated).
|
|
136
116
|
|
|
137
117
|
---
|
|
138
118
|
|
|
@@ -223,13 +203,7 @@ import { motionSpring, fadeInUp, blockStagger } from "@/lib/motion"
|
|
|
223
203
|
|
|
224
204
|
### Spring Presets
|
|
225
205
|
|
|
226
|
-
|
|
227
|
-
|------|-----------|---------|------|---------|
|
|
228
|
-
| `snappy` | 400 | 28 | 0.8 | Micro-interactions, tooltips |
|
|
229
|
-
| `gentle` | 200 | 20 | 1.0 | Page transitions, drawers |
|
|
230
|
-
| `bouncy` | 300 | 14 | 0.8 | Celebration, completion |
|
|
231
|
-
| `dramatic` | 500 | 24 | 1.2 | Hero entrances |
|
|
232
|
-
| `wobbly` | bloom only | | | Extra bounce |
|
|
206
|
+
`snappy` (micro-interactions), `gentle` (page transitions), `bouncy` (celebration), `dramatic` (hero entrances), `wobbly` (bloom only). Full values: `references/animation.md`.
|
|
233
207
|
|
|
234
208
|
### Duration Tokens
|
|
235
209
|
|
|
@@ -267,19 +241,7 @@ import { SettingsIcon, BellIcon } from "@vadimcomanescu/nadicode-design-system/i
|
|
|
267
241
|
|
|
268
242
|
**Total: 399 icons.** Before adding a new icon, check whether it already exports from `@vadimcomanescu/nadicode-design-system/icons` or a matching `@vadimcomanescu/nadicode-design-system/icons/<name>` subpath.
|
|
269
243
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
1. **Check if it exists** (399 total -- likely yes).
|
|
273
|
-
2. **If missing:** add it to `lucide-wrapped.tsx` using `createAnimatedIcon`:
|
|
274
|
-
```tsx
|
|
275
|
-
import { Home } from "lucide-react"
|
|
276
|
-
export const HomeIcon = createAnimatedIcon(Home, "HomeIcon")
|
|
277
|
-
```
|
|
278
|
-
3. **If the needed icon is missing**, stop and request an upstream DS export. Do not hand-craft a local scaffold copy just to bypass the package contract.
|
|
279
|
-
|
|
280
|
-
`createAnimatedIcon` is also exported for consumers to wrap any Lucide icon ad-hoc without adding it to the catalog.
|
|
281
|
-
|
|
282
|
-
Full catalog: `references/icons.md`
|
|
244
|
+
If an icon is missing, add it to `lucide-wrapped.tsx` via `createAnimatedIcon`. Do not hand-craft local copies to bypass the package contract.
|
|
283
245
|
|
|
284
246
|
---
|
|
285
247
|
|
|
@@ -328,6 +290,8 @@ Every page = **Shell > Sections > Components**.
|
|
|
328
290
|
- 2-8 sections (vertical bands, no nesting)
|
|
329
291
|
- 1-6 components per section via CSS grid/flex
|
|
330
292
|
|
|
293
|
+
Page-kits in the catalog ARE the ready-made compositions. Use `seedComponents.<Name>PageKit` from `@vadimcomanescu/nadicode-design-system/catalog/components` rather than assembling pages by hand.
|
|
294
|
+
|
|
331
295
|
### Shell Selection
|
|
332
296
|
|
|
333
297
|
| Intent | Shell | Components |
|
|
@@ -340,69 +304,9 @@ Every page = **Shell > Sections > Components**.
|
|
|
340
304
|
|
|
341
305
|
Content widths, vertical rhythm, responsive contracts: `references/composition.md`
|
|
342
306
|
|
|
343
|
-
### Kanban Board
|
|
307
|
+
### Kanban Board
|
|
344
308
|
|
|
345
|
-
Compound component
|
|
346
|
-
|
|
347
|
-
```tsx
|
|
348
|
-
import {
|
|
349
|
-
KanbanBoard, KanbanColumn, KanbanColumnHeader,
|
|
350
|
-
KanbanItem, KanbanHandle,
|
|
351
|
-
} from '@vadimcomanescu/nadicode-design-system/kanban-board'
|
|
352
|
-
import type { KanbanColumnState, KanbanMoveMeta } from '@vadimcomanescu/nadicode-design-system/kanban-board'
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
**Architecture:** `@dnd-kit/core` + `@dnd-kit/sortable` internally. Consumer API is Seed-owned (no dnd-kit types leak).
|
|
356
|
-
|
|
357
|
-
**Usage:**
|
|
358
|
-
|
|
359
|
-
```tsx
|
|
360
|
-
type Task = { id: string; title: string }
|
|
361
|
-
|
|
362
|
-
const [columns, setColumns] = useState<KanbanColumnState<Task>[]>([
|
|
363
|
-
{ id: 'todo', items: [{ id: '1', title: 'Task A' }] },
|
|
364
|
-
{ id: 'done', items: [] },
|
|
365
|
-
])
|
|
366
|
-
|
|
367
|
-
<KanbanBoard
|
|
368
|
-
value={columns}
|
|
369
|
-
onValueChange={(next, meta) => {
|
|
370
|
-
setColumns([...next])
|
|
371
|
-
// meta: { item, itemId, fromColumnId, toColumnId, fromIndex, toIndex }
|
|
372
|
-
}}
|
|
373
|
-
getItemId={(task) => task.id}
|
|
374
|
-
getItemLabel={(task) => task.title}
|
|
375
|
-
canMove={({ fromColumnId, toColumnId }) => isAllowed(fromColumnId, toColumnId)}
|
|
376
|
-
renderOverlay={(task) => <MyCard task={task} />}
|
|
377
|
-
>
|
|
378
|
-
{columns.map((col) => (
|
|
379
|
-
<KanbanColumn key={col.id} id={col.id} items={col.items} aria-label={col.name}>
|
|
380
|
-
<KanbanColumnHeader>{col.name} <Badge variant="outline">{col.items.length}</Badge></KanbanColumnHeader>
|
|
381
|
-
{col.items.map((task) => (
|
|
382
|
-
<KanbanItem key={task.id} value={task}>
|
|
383
|
-
<KanbanHandle aria-label={`Move ${task.title}`} />
|
|
384
|
-
<MyCard task={task} />
|
|
385
|
-
</KanbanItem>
|
|
386
|
-
))}
|
|
387
|
-
</KanbanColumn>
|
|
388
|
-
))}
|
|
389
|
-
</KanbanBoard>
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
**Key props:**
|
|
393
|
-
|
|
394
|
-
| Prop | Required | Purpose |
|
|
395
|
-
|------|----------|---------|
|
|
396
|
-
| `value` | Yes | `KanbanColumnState<T>[]` -- controlled column state |
|
|
397
|
-
| `onValueChange` | Yes | `(next, meta) => void` -- fires with new state + move metadata |
|
|
398
|
-
| `getItemId` | Yes | Extract stable ID from item |
|
|
399
|
-
| `getItemLabel` | No | Human label for screen reader announcements |
|
|
400
|
-
| `canMove` | No | Constraint callback to reject moves |
|
|
401
|
-
| `renderOverlay` | No | Custom drag ghost (renders inside `glass-floating`) |
|
|
402
|
-
| `activationDistance` | No | Px before drag starts (default: 5) |
|
|
403
|
-
| `items` on Column | Yes | Pass the column's items array for SortableContext |
|
|
404
|
-
|
|
405
|
-
**Card content is consumer-owned.** The DS provides the board structure, drag mechanics, glass styling, and accessibility. Compose card interiors from existing DS primitives: `Badge`, `StatusDot`, `Typography`, `Button`, `Avatar`.
|
|
309
|
+
Compound component via `seedComponents`. Uses `@dnd-kit` internally (no dnd-kit types leak). Card content is consumer-owned. See catalog entry for full props and sub-components. Types: `@vadimcomanescu/nadicode-design-system/kanban-board`.
|
|
406
310
|
|
|
407
311
|
---
|
|
408
312
|
|
|
@@ -415,46 +319,14 @@ Patterns: `references/state-machines.md`
|
|
|
415
319
|
|
|
416
320
|
---
|
|
417
321
|
|
|
418
|
-
## Recipe Index
|
|
419
|
-
|
|
420
|
-
| Intent | Recipe | Shell |
|
|
421
|
-
|--------|--------|-------|
|
|
422
|
-
| Dashboard | `recipes/dashboard.md` | app-shell |
|
|
423
|
-
| Marketing Landing | `recipes/marketing-landing.md` | marketing-shell |
|
|
424
|
-
| Agency Home | `recipes/agency-home.md` | marketing-shell |
|
|
425
|
-
| Digital Workers | `recipes/digital-workers.md` | marketing-shell |
|
|
426
|
-
| Service Detail | `recipes/service-detail.md` | marketing-shell |
|
|
427
|
-
| CRUD List + Detail | `recipes/crud-list-detail.md` | app-shell |
|
|
428
|
-
| CRUD Form | `recipes/crud-form.md` | app-shell |
|
|
429
|
-
| Settings | `recipes/settings.md` | app-shell |
|
|
430
|
-
| Auth | `recipes/auth.md` | auth-shell |
|
|
431
|
-
| Onboarding | `recipes/onboarding.md` | onboarding-shell |
|
|
432
|
-
| Pricing | `recipes/pricing.md` | marketing-shell |
|
|
433
|
-
| Analytics | `recipes/analytics.md` | app-shell |
|
|
434
|
-
| Agent Chat | `recipes/agents-chat.md` | app-shell |
|
|
435
|
-
| Error Pages | `recipes/error-pages.md` | fallback-shell |
|
|
436
|
-
| Navigation Shell | `recipes/navigation-shell.md` | app-shell |
|
|
437
|
-
| Blog / Content | `recipes/blog-content.md` | marketing-shell |
|
|
438
|
-
| Company About | `recipes/company-about.md` | marketing-shell |
|
|
439
|
-
| Company Contact | `recipes/company-contact.md` | marketing-shell |
|
|
440
|
-
| Marketing Shell | `recipes/marketing-shell.md` | marketing-shell |
|
|
441
|
-
| Checkout | `recipes/checkout.md` | marketing-shell |
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
322
|
## Reference Index
|
|
446
323
|
|
|
447
324
|
| File | Contents |
|
|
448
325
|
|------|----------|
|
|
449
|
-
| `references/tokens.md` | Radix scales, semantic token map, CSS variables, bloom palette |
|
|
450
|
-
| `references/components.md` | All UI components with tiers inline, Radix primitives, agentic UI |
|
|
451
326
|
| `references/patterns.md` | Golden pattern + 4 code examples: Button, Input, Dialog, LoginBlock |
|
|
452
327
|
| `references/animation.md` | Springs, easings, durations, stagger, choreography, reduced motion |
|
|
453
328
|
| `references/glass-and-effects.md` | Glass tier CSS, decorative components, text effects, shaders |
|
|
454
|
-
| `references/blocks.md` | Blocks by domain with import paths |
|
|
455
|
-
| `references/icons.md` | Animated icon usage patterns |
|
|
456
329
|
| `references/opinions.md` | Decision tables from Opinions Bible |
|
|
457
|
-
| `references/nextjs.md` | App Router setup, providers, SSR boundaries, showcase |
|
|
458
330
|
| `references/composition.md` | Layout algebra, spacing, grid patterns, content widths |
|
|
459
331
|
| `references/responsive.md` | Breakpoint contracts, mobile-first, touch targets |
|
|
460
332
|
| `references/state-machines.md` | State machines, loading tiers, streaming, error handling |
|
|
@@ -90,7 +90,7 @@ What is the element?
|
|
|
90
90
|
|
|
91
91
|
## Storyboard Format
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
Animation storyboard format (use when documenting page-kit entrance sequences):
|
|
94
94
|
|
|
95
95
|
```
|
|
96
96
|
ANIMATION STORYBOARD
|
|
@@ -254,7 +254,7 @@ When `prefers-reduced-motion` is active:
|
|
|
254
254
|
- ScrollFadeIn elements visible immediately
|
|
255
255
|
- Continuous animations (aurora, shimmer, meteor) paused via CSS
|
|
256
256
|
|
|
257
|
-
Every
|
|
257
|
+
Every storyboard includes a `REDUCED` line specifying fallback behavior when `prefers-reduced-motion` is active.
|
|
258
258
|
|
|
259
259
|
---
|
|
260
260
|
|
|
@@ -17,7 +17,7 @@ Breakpoint contracts, mobile-first patterns, touch targets, and responsive rules
|
|
|
17
17
|
|
|
18
18
|
**Design priority**: Mobile-first. Default styles target mobile, add complexity at breakpoints.
|
|
19
19
|
|
|
20
|
-
**Primary breakpoints
|
|
20
|
+
**Primary breakpoints**: default, `sm:`, `lg:`, `xl:`. Use `md:` and `2xl:` sparingly.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
package/README.md
CHANGED
|
@@ -15,12 +15,13 @@ The dev server runs on `http://localhost:5001` and serves the showcase routes un
|
|
|
15
15
|
|
|
16
16
|
Consumer apps install Seed through an exact released package version. For unpublished local work, stage a tarball under `.nadicode/packages/` and install that committed relative artifact instead. Do not point apps at a live DS repo directory.
|
|
17
17
|
|
|
18
|
+
Component discovery and consumption go through the catalog. Blocks and page-kits have no individual subpath exports.
|
|
19
|
+
|
|
18
20
|
Canonical consumer docs:
|
|
19
21
|
|
|
20
22
|
- [docs/nadicode/SCAFFOLDING_PROCESS.md](docs/nadicode/SCAFFOLDING_PROCESS.md), normative runtime and ownership contract
|
|
21
23
|
- [docs/nadicode/ADOPTION_PLAYBOOK.md](docs/nadicode/ADOPTION_PLAYBOOK.md), step-by-step install and wiring flow
|
|
22
24
|
- [.agents/skills/seed/SKILL.md](.agents/skills/seed/SKILL.md), synced agent-facing usage guide
|
|
23
|
-
- [.agents/skills/seed/contract.md](.agents/skills/seed/contract.md), synced binary consumer rules
|
|
24
25
|
|
|
25
26
|
## Canonical Sources
|
|
26
27
|
|
|
@@ -31,7 +32,6 @@ The repo treats structured truth and prose differently.
|
|
|
31
32
|
- Public package surface lives in `package.json` exports, `src/catalog/catalog.ts`, and `bin/shipped-files.json`.
|
|
32
33
|
- Consumer ownership and package-backed runtime rules live in [docs/nadicode/SCAFFOLDING_PROCESS.md](docs/nadicode/SCAFFOLDING_PROCESS.md).
|
|
33
34
|
- Release steps live in [docs/releasing-package.md](docs/releasing-package.md).
|
|
34
|
-
- Component metadata lives in `dist/catalog/catalog.js`, generated from `src/catalog/catalog.ts`.
|
|
35
35
|
|
|
36
36
|
Use prose docs for guidance and rationale. Use scripts, manifests, and generated artifacts for anything that must stay machine-accurate.
|
|
37
37
|
|
|
@@ -7,14 +7,14 @@ import { PricingPageKit } from '../chunk-RMGDDOCD.js';
|
|
|
7
7
|
import { ProfileSettingsPageKit } from '../chunk-MGSGCARB.js';
|
|
8
8
|
import { RecoveryPageKit } from '../chunk-BRCBJ3S4.js';
|
|
9
9
|
import { ResetPageKit } from '../chunk-LP6ZZYOQ.js';
|
|
10
|
-
import { ServiceSuitePageKit } from '../chunk-
|
|
10
|
+
import { ServiceSuitePageKit } from '../chunk-K4U67BVG.js';
|
|
11
11
|
import { SettingsPageKit } from '../chunk-RKQPU75I.js';
|
|
12
12
|
import { SignupPageKit } from '../chunk-BRICSLHJ.js';
|
|
13
13
|
import { SuccessPageKit } from '../chunk-3U56FXYC.js';
|
|
14
14
|
import { DashboardPageKit } from '../chunk-C33GUEDY.js';
|
|
15
15
|
import { ErrorPageKit } from '../chunk-HPTHS7SX.js';
|
|
16
16
|
import { KanbanBoardPageKit } from '../chunk-25BOZMXA.js';
|
|
17
|
-
import { LandingPageKit } from '../chunk-
|
|
17
|
+
import { LandingPageKit } from '../chunk-LK2L3C7D.js';
|
|
18
18
|
import { LoginPageKit } from '../chunk-Z2WION42.js';
|
|
19
19
|
import { OnboardingPageKit } from '../chunk-BYEHHZZN.js';
|
|
20
20
|
import { AccountLockedPageKit } from '../chunk-DNJEVMDY.js';
|
|
@@ -52,7 +52,7 @@ import { PasswordRecoveryBlock } from '../chunk-5PZ4VR2D.js';
|
|
|
52
52
|
import { PricingBlock } from '../chunk-VNNAL4A6.js';
|
|
53
53
|
import '../chunk-DARC2ACH.js';
|
|
54
54
|
import { GalleryBlock } from '../chunk-FTGFOK6T.js';
|
|
55
|
-
import { HeroBlock } from '../chunk-
|
|
55
|
+
import { HeroBlock } from '../chunk-GJ557DGH.js';
|
|
56
56
|
import { HeroSectionBlock } from '../chunk-ALA6OM7K.js';
|
|
57
57
|
import '../chunk-QQOWC53X.js';
|
|
58
58
|
import { HeaderBlock } from '../chunk-WOYBVPXK.js';
|
|
@@ -182,7 +182,7 @@ import '../chunk-D4NC7WX5.js';
|
|
|
182
182
|
import '../chunk-5UESKK6S.js';
|
|
183
183
|
import '../chunk-NAAU5IWU.js';
|
|
184
184
|
import '../chunk-4S326Z3D.js';
|
|
185
|
-
import '../chunk-
|
|
185
|
+
import '../chunk-POFFOUQW.js';
|
|
186
186
|
import '../chunk-GJUR6HT3.js';
|
|
187
187
|
import '../chunk-7KIDDF3I.js';
|
|
188
188
|
import '../chunk-4GSFNJAJ.js';
|
|
@@ -3,7 +3,7 @@ import { AnimatedGradientText } from './chunk-XZ3A33GP.js';
|
|
|
3
3
|
import { Heading } from './chunk-WI547C47.js';
|
|
4
4
|
import { siteConfig } from './chunk-A7NUWD76.js';
|
|
5
5
|
import { Card, CardHeader, CardContent } from './chunk-AH6YSYYT.js';
|
|
6
|
-
import { MouseGlow } from './chunk-
|
|
6
|
+
import { MouseGlow } from './chunk-POFFOUQW.js';
|
|
7
7
|
import { Button } from './chunk-7KIDDF3I.js';
|
|
8
8
|
import { m, heroStagger } from './chunk-PD2YEH3H.js';
|
|
9
9
|
import { ZapIcon } from './chunk-FLF5AMNO.js';
|
|
@@ -2,7 +2,7 @@ import { MarketingShellPageKit } from './chunk-Z233ZQZE.js';
|
|
|
2
2
|
import { TeamBlock } from './chunk-VBZQ4DBE.js';
|
|
3
3
|
import { TestimonialsBlock } from './chunk-FV2G6SAF.js';
|
|
4
4
|
import { ProcessFlowBlock } from './chunk-HZERHGBT.js';
|
|
5
|
-
import { HeroBlock } from './chunk-
|
|
5
|
+
import { HeroBlock } from './chunk-GJ557DGH.js';
|
|
6
6
|
import { FAQBlock } from './chunk-NEHCPO53.js';
|
|
7
7
|
import { FeatureBlock } from './chunk-HJ3A2YNO.js';
|
|
8
8
|
import { CallToActionBlock } from './chunk-GJPTPLCQ.js';
|
|
@@ -3,7 +3,7 @@ import { SocialProofBlock } from './chunk-C7WHMSF3.js';
|
|
|
3
3
|
import { StatsMarketingBlock } from './chunk-QIHA7S3A.js';
|
|
4
4
|
import { NewsletterBlock } from './chunk-K7NQ6ZAW.js';
|
|
5
5
|
import { PricingBlock } from './chunk-VNNAL4A6.js';
|
|
6
|
-
import { HeroBlock } from './chunk-
|
|
6
|
+
import { HeroBlock } from './chunk-GJ557DGH.js';
|
|
7
7
|
import { FAQBlock } from './chunk-NEHCPO53.js';
|
|
8
8
|
import { FeatureBlock } from './chunk-HJ3A2YNO.js';
|
|
9
9
|
import { CallToActionBlock } from './chunk-GJPTPLCQ.js';
|
|
@@ -5,10 +5,7 @@ import { createPortal } from 'react-dom';
|
|
|
5
5
|
import { useReducedMotion, useMotionValue, useMotionTemplate } from 'motion/react';
|
|
6
6
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
if (typeof window === "undefined") return "10 158 111";
|
|
10
|
-
return getComputedStyle(document.documentElement).getPropertyValue("--color-accent").trim() || "10 158 111";
|
|
11
|
-
}
|
|
8
|
+
var CSS_ACCENT_095 = "rgb(var(--color-accent) / 0.95)";
|
|
12
9
|
function MouseGlow({
|
|
13
10
|
className,
|
|
14
11
|
dotColor = "rgba(255, 255, 255, 0.5)",
|
|
@@ -20,7 +17,7 @@ function MouseGlow({
|
|
|
20
17
|
const containerRef = React.useRef(null);
|
|
21
18
|
const overlayRef = React.useRef(null);
|
|
22
19
|
const [mounted, setMounted] = React.useState(false);
|
|
23
|
-
const resolvedOverlayColor = overlayColor ??
|
|
20
|
+
const resolvedOverlayColor = overlayColor ?? CSS_ACCENT_095;
|
|
24
21
|
React.useEffect(() => {
|
|
25
22
|
setMounted(true);
|
|
26
23
|
const handleMouseMove = (e) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { HeroBlock } from '../../chunk-
|
|
2
|
+
export { HeroBlock } from '../../chunk-GJ557DGH.js';
|
|
3
3
|
import '../../chunk-G5EO22OR.js';
|
|
4
4
|
import '../../chunk-OHX2LFAH.js';
|
|
5
5
|
import '../../chunk-SGI25ZJ6.js';
|
|
@@ -14,7 +14,7 @@ import '../../chunk-4O6L5YWT.js';
|
|
|
14
14
|
import '../../chunk-WI547C47.js';
|
|
15
15
|
import '../../chunk-A7NUWD76.js';
|
|
16
16
|
import '../../chunk-AH6YSYYT.js';
|
|
17
|
-
import '../../chunk-
|
|
17
|
+
import '../../chunk-POFFOUQW.js';
|
|
18
18
|
import '../../chunk-7KIDDF3I.js';
|
|
19
19
|
import '../../chunk-PD2YEH3H.js';
|
|
20
20
|
import '../../chunk-CRY67BIF.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { LandingPageKit } from '../../chunk-
|
|
1
|
+
export { LandingPageKit } from '../../chunk-LK2L3C7D.js';
|
|
2
2
|
import '../../chunk-Z233ZQZE.js';
|
|
3
3
|
import '../../chunk-C7WHMSF3.js';
|
|
4
4
|
import '../../chunk-QIHA7S3A.js';
|
|
5
5
|
import '../../chunk-K7NQ6ZAW.js';
|
|
6
6
|
import '../../chunk-VNNAL4A6.js';
|
|
7
7
|
import '../../chunk-DARC2ACH.js';
|
|
8
|
-
import '../../chunk-
|
|
8
|
+
import '../../chunk-GJ557DGH.js';
|
|
9
9
|
import '../../chunk-QQOWC53X.js';
|
|
10
10
|
import '../../chunk-WOYBVPXK.js';
|
|
11
11
|
import '../../chunk-NEHCPO53.js';
|
|
@@ -38,7 +38,7 @@ import '../../chunk-LIBXYD5Q.js';
|
|
|
38
38
|
import '../../chunk-I23DDSU7.js';
|
|
39
39
|
import '../../chunk-AH6YSYYT.js';
|
|
40
40
|
import '../../chunk-NAAU5IWU.js';
|
|
41
|
-
import '../../chunk-
|
|
41
|
+
import '../../chunk-POFFOUQW.js';
|
|
42
42
|
import '../../chunk-7KIDDF3I.js';
|
|
43
43
|
import '../../chunk-6FOHUNXR.js';
|
|
44
44
|
import '../../chunk-PD2YEH3H.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { ServiceSuitePageKit } from '../../chunk-
|
|
1
|
+
export { ServiceSuitePageKit } from '../../chunk-K4U67BVG.js';
|
|
2
2
|
import '../../chunk-Z233ZQZE.js';
|
|
3
3
|
import '../../chunk-VBZQ4DBE.js';
|
|
4
4
|
import '../../chunk-FV2G6SAF.js';
|
|
5
5
|
import '../../chunk-HZERHGBT.js';
|
|
6
|
-
import '../../chunk-
|
|
6
|
+
import '../../chunk-GJ557DGH.js';
|
|
7
7
|
import '../../chunk-QQOWC53X.js';
|
|
8
8
|
import '../../chunk-WOYBVPXK.js';
|
|
9
9
|
import '../../chunk-NEHCPO53.js';
|
|
@@ -33,7 +33,7 @@ import '../../chunk-LIBXYD5Q.js';
|
|
|
33
33
|
import '../../chunk-I23DDSU7.js';
|
|
34
34
|
import '../../chunk-AH6YSYYT.js';
|
|
35
35
|
import '../../chunk-NAAU5IWU.js';
|
|
36
|
-
import '../../chunk-
|
|
36
|
+
import '../../chunk-POFFOUQW.js';
|
|
37
37
|
import '../../chunk-7KIDDF3I.js';
|
|
38
38
|
import '../../chunk-6FOHUNXR.js';
|
|
39
39
|
import '../../chunk-PD2YEH3H.js';
|
|
@@ -83,6 +83,7 @@ export const nadicodeRules = {
|
|
|
83
83
|
"nadicode/no-handcoded-empty-state": "error",
|
|
84
84
|
"nadicode/no-handcoded-field": "error",
|
|
85
85
|
"nadicode/require-catalog-component": "error",
|
|
86
|
+
"nadicode/require-catalog-import": "error",
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
function normalizePattern(pattern) {
|
|
@@ -70,6 +70,7 @@ import noHandcodedHeading from "./rules/no-handcoded-heading.js";
|
|
|
70
70
|
import noHandcodedEmptyState from "./rules/no-handcoded-empty-state.js";
|
|
71
71
|
import noHandcodedField from "./rules/no-handcoded-field.js";
|
|
72
72
|
import requireCatalogComponent from "./rules/require-catalog-component.js";
|
|
73
|
+
import requireCatalogImport from "./rules/require-catalog-import.js";
|
|
73
74
|
|
|
74
75
|
export { nadicodeRules, createAllowlistOverrides } from "./config.js";
|
|
75
76
|
|
|
@@ -147,5 +148,6 @@ export const nadicodePlugin = {
|
|
|
147
148
|
"no-handcoded-empty-state": noHandcodedEmptyState,
|
|
148
149
|
"no-handcoded-field": noHandcodedField,
|
|
149
150
|
"require-catalog-component": requireCatalogComponent,
|
|
151
|
+
"require-catalog-import": requireCatalogImport,
|
|
150
152
|
},
|
|
151
153
|
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { RuleTester } from "eslint";
|
|
2
|
+
import { describe } from "vitest";
|
|
3
|
+
|
|
4
|
+
import rule from "../require-catalog-import.js";
|
|
5
|
+
|
|
6
|
+
const tester = new RuleTester({
|
|
7
|
+
languageOptions: {
|
|
8
|
+
ecmaVersion: "latest",
|
|
9
|
+
sourceType: "module",
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe("require-catalog-import", () => {
|
|
14
|
+
tester.run("require-catalog-import", rule, {
|
|
15
|
+
valid: [
|
|
16
|
+
// Catalog import (correct pattern)
|
|
17
|
+
{
|
|
18
|
+
code: "import { seedComponents } from '@/catalog/components';",
|
|
19
|
+
filename: "/repo/src/app/page.tsx",
|
|
20
|
+
},
|
|
21
|
+
// UI primitive (not a block/page-kit)
|
|
22
|
+
{
|
|
23
|
+
code: "import { Button } from '@/components/ui/Button';",
|
|
24
|
+
filename: "/repo/src/app/page.tsx",
|
|
25
|
+
},
|
|
26
|
+
// Type-only imports are allowed (importKind === "type"), but require TS parser to test.
|
|
27
|
+
// Verified in production via TypeScript ESLint config.
|
|
28
|
+
// Test files are exempt
|
|
29
|
+
{
|
|
30
|
+
code: "import { HeroBlock } from '@/components/blocks/HeroBlock';",
|
|
31
|
+
filename: "/repo/src/components/blocks/__tests__/HeroBlock.test.tsx",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
code: "import { HeroBlock } from '../../blocks/HeroBlock';",
|
|
35
|
+
filename: "/repo/src/components/blocks/HeroBlock.spec.tsx",
|
|
36
|
+
},
|
|
37
|
+
// Catalog barrel itself is exempt
|
|
38
|
+
{
|
|
39
|
+
code: "import { HeroBlock } from '@/components/blocks/HeroBlock';",
|
|
40
|
+
filename: "/repo/src/catalog/components.tsx",
|
|
41
|
+
},
|
|
42
|
+
// Block source files are exempt (internal composition)
|
|
43
|
+
{
|
|
44
|
+
code: "import { AuthLayout } from '../blocks/AuthLayout';",
|
|
45
|
+
filename: "/repo/src/components/blocks/LoginBlock.tsx",
|
|
46
|
+
},
|
|
47
|
+
// Page-kit source files are exempt
|
|
48
|
+
{
|
|
49
|
+
code: "import { HeaderBlock } from '../blocks/HeaderBlock';",
|
|
50
|
+
filename: "/repo/src/components/page-kits/LandingPageKit.tsx",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
invalid: [
|
|
54
|
+
// Direct block import via absolute alias
|
|
55
|
+
{
|
|
56
|
+
code: "import { HeroBlock } from '@/components/blocks/HeroBlock';",
|
|
57
|
+
filename: "/repo/src/app/page.tsx",
|
|
58
|
+
errors: [
|
|
59
|
+
{
|
|
60
|
+
message:
|
|
61
|
+
"Import 'HeroBlock' from '@/catalog/components' via seedComponents. Direct block/page-kit imports are not allowed (ADR 0009).",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
// Direct page-kit import via absolute alias
|
|
66
|
+
{
|
|
67
|
+
code: "import { LandingPageKit } from '@/components/page-kits/LandingPageKit';",
|
|
68
|
+
filename: "/repo/src/app/page.tsx",
|
|
69
|
+
errors: [
|
|
70
|
+
{
|
|
71
|
+
message:
|
|
72
|
+
"Import 'LandingPageKit' from '@/catalog/components' via seedComponents. Direct block/page-kit imports are not allowed (ADR 0009).",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
// Relative block import from pages directory
|
|
77
|
+
{
|
|
78
|
+
code: "import { HeroBlock } from '../../blocks/HeroBlock';",
|
|
79
|
+
filename: "/repo/src/components/pages/showcase/BlocksShowcase.tsx",
|
|
80
|
+
errors: [
|
|
81
|
+
{
|
|
82
|
+
message:
|
|
83
|
+
"Import 'HeroBlock' from '@/catalog/components' via seedComponents. Direct block/page-kit imports are not allowed (ADR 0009).",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
// Relative block import (one level up)
|
|
88
|
+
{
|
|
89
|
+
code: "import { FooterBlock } from '../blocks/FooterBlock';",
|
|
90
|
+
filename: "/repo/src/components/pages/LandingPage.tsx",
|
|
91
|
+
errors: [
|
|
92
|
+
{
|
|
93
|
+
message:
|
|
94
|
+
"Import 'FooterBlock' from '@/catalog/components' via seedComponents. Direct block/page-kit imports are not allowed (ADR 0009).",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
// Nested block path (e.g., blocks/user/InviteUserModal)
|
|
99
|
+
{
|
|
100
|
+
code: "import { InviteUserModal } from '../../blocks/user/InviteUserModal';",
|
|
101
|
+
filename: "/repo/src/components/pages/settings/TeamPage.tsx",
|
|
102
|
+
errors: [
|
|
103
|
+
{
|
|
104
|
+
message:
|
|
105
|
+
"Import 'InviteUserModal' from '@/catalog/components' via seedComponents. Direct block/page-kit imports are not allowed (ADR 0009).",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -19,7 +19,7 @@ function reportMatches(context, node, tokens) {
|
|
|
19
19
|
context.report({
|
|
20
20
|
node,
|
|
21
21
|
message:
|
|
22
|
-
"Selector '{{sel}}' breaks with animated icon wrappers. Use a data-slot sub-component instead (see
|
|
22
|
+
"Selector '{{sel}}' breaks with animated icon wrappers. Use a data-slot sub-component instead (see references/patterns.md).",
|
|
23
23
|
data: { sel: hit },
|
|
24
24
|
});
|
|
25
25
|
}
|