@spark-web/design-system 5.1.4 → 5.1.5
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/CLAUDE.md +38 -192
- package/package.json +19 -20
- package/patterns/CLAUDE.md +75 -35
- package/patterns/internal-admin/CLAUDE.md +7 -19
- package/patterns/internal-admin/{details-page.md → detail-page.md} +114 -51
- package/patterns/internal-admin/list-page.md +199 -137
- package/patterns/internal-admin/portal-hub.md +165 -0
- package/patterns/vendor-admin/CLAUDE.md +216 -0
- package/patterns/vendor-admin/dashboard.md +681 -0
- package/patterns/vendor-admin/form-page.md +504 -0
- package/patterns/vendor-admin/list-page.md +709 -0
- package/patterns/vendor-admin/vendor-portal.md +309 -0
- package/ai-context/layer-1-root.md +0 -158
- package/ai-context/layer-2-surface-pattern.md +0 -236
- package/ai-context/layer-3-component.md +0 -271
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Internal admin —
|
|
1
|
+
# Internal admin — detail page pattern
|
|
2
2
|
|
|
3
3
|
## Before using this pattern
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Surface rules: read
|
|
6
|
+
`node_modules/@spark-web/design-system/patterns/internal-admin/CLAUDE.md` in
|
|
7
|
+
full first — its rules all apply here.
|
|
8
8
|
|
|
9
9
|
## What this pattern is
|
|
10
10
|
|
|
@@ -15,11 +15,9 @@ header dropdown.
|
|
|
15
15
|
|
|
16
16
|
## When to use this pattern
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
- A page showing a record's fields, history, or associated sub-records
|
|
22
|
-
- The words "detail", "profile", "view", "record page", or "user/vendor page"
|
|
18
|
+
Any single-record detail/profile view — the registry
|
|
19
|
+
(`node_modules/@spark-web/design-system/patterns/CLAUDE.md`) owns surface and
|
|
20
|
+
feature-type classification.
|
|
23
21
|
|
|
24
22
|
---
|
|
25
23
|
|
|
@@ -27,20 +25,23 @@ Use this pattern when the PRD describes any of the following:
|
|
|
27
25
|
|
|
28
26
|
Read these before implementing — they own the component-level rules:
|
|
29
27
|
|
|
30
|
-
- `
|
|
31
|
-
vs. disable
|
|
32
|
-
- `
|
|
33
|
-
|
|
34
|
-
- `
|
|
35
|
-
expandable rows
|
|
36
|
-
- `
|
|
37
|
-
guard
|
|
38
|
-
- `
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- `
|
|
42
|
-
- `
|
|
43
|
-
- `
|
|
28
|
+
- `node_modules/@spark-web/action-dropdown/CLAUDE.md` — dropdown construction,
|
|
29
|
+
ordering, hide vs. disable
|
|
30
|
+
- `node_modules/@spark-web/modal-dialog/CLAUDE.md` — ContentDialog API, admin
|
|
31
|
+
modal sizing, destructive modal anatomy
|
|
32
|
+
- `node_modules/@spark-web/data-table/CLAUDE.md` — DataTable API, loading/empty
|
|
33
|
+
states, expandable rows
|
|
34
|
+
- `node_modules/@spark-web/tabs/CLAUDE.md` — Tabs API, internal-admin background
|
|
35
|
+
override, null guard
|
|
36
|
+
- `node_modules/@spark-web/section-card/CLAUDE.md` — SectionCard API
|
|
37
|
+
- `node_modules/@spark-web/section-header/CLAUDE.md` — SectionHeader API, for
|
|
38
|
+
SectionCard headers
|
|
39
|
+
- `node_modules/@spark-web/badge/CLAUDE.md` — status tone mapping
|
|
40
|
+
- `node_modules/@spark-web/columns/CLAUDE.md` — responsive two-column layout
|
|
41
|
+
- `node_modules/@spark-web/box/CLAUDE.md` — flex layout utilities
|
|
42
|
+
- `node_modules/@spark-web/stack/CLAUDE.md` — vertical stacking and gap
|
|
43
|
+
- `node_modules/@spark-web/heading/CLAUDE.md` — detail-page H1
|
|
44
|
+
- `node_modules/@spark-web/alert/CLAUDE.md` — page-level feedback Alert
|
|
44
45
|
|
|
45
46
|
---
|
|
46
47
|
|
|
@@ -55,8 +56,8 @@ Outer wrapper Stack paddingX="xlarge" paddingY="xxlarge" gap="xlarg
|
|
|
55
56
|
Left column Stack gap="xlarge" — primary record fields + primary sub-tables
|
|
56
57
|
Right column Stack gap="xlarge" — secondary/contextual sections
|
|
57
58
|
SectionCard (per section)
|
|
58
|
-
DataTable PAGE_SIZE=5 items; see data-table/CLAUDE.md
|
|
59
|
-
TablePagination only when total > PAGE_SIZE
|
|
59
|
+
DataTable PAGE_SIZE=5 items; see node_modules/@spark-web/data-table/CLAUDE.md
|
|
60
|
+
TablePagination consumer-supplied — only when total > PAGE_SIZE
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
---
|
|
@@ -92,7 +93,7 @@ All spacing uses Spark tokens. This is distinct from list-page spacing
|
|
|
92
93
|
</Box>
|
|
93
94
|
|
|
94
95
|
{actions.length > 0 && (
|
|
95
|
-
<Box
|
|
96
|
+
<Box css={{ minWidth: 130 }}>
|
|
96
97
|
<ActionDropdown label="Actions" actions={actions} />
|
|
97
98
|
</Box>
|
|
98
99
|
)}
|
|
@@ -109,7 +110,8 @@ Rules:
|
|
|
109
110
|
|
|
110
111
|
## Section 3 — Actions dropdown
|
|
111
112
|
|
|
112
|
-
See `
|
|
113
|
+
See `node_modules/@spark-web/action-dropdown/CLAUDE.md` for full API and
|
|
114
|
+
ordering rules.
|
|
113
115
|
|
|
114
116
|
Page-level decisions:
|
|
115
117
|
|
|
@@ -141,14 +143,14 @@ State shape: `{ isSuccessful: boolean; message: string } | undefined`
|
|
|
141
143
|
|
|
142
144
|
Rendered between the header and content columns. Only used for direct inline
|
|
143
145
|
mutations. Modal confirmations own their own error Alert inside the
|
|
144
|
-
`ContentDialog` — see `
|
|
146
|
+
`ContentDialog` — see `node_modules/@spark-web/modal-dialog/CLAUDE.md`.
|
|
145
147
|
|
|
146
148
|
---
|
|
147
149
|
|
|
148
150
|
## Section 5 — Confirmation modals
|
|
149
151
|
|
|
150
|
-
See `
|
|
151
|
-
form-in-modal anatomy, and the full destructive modal pattern.
|
|
152
|
+
See `node_modules/@spark-web/modal-dialog/CLAUDE.md` for ContentDialog API,
|
|
153
|
+
sizing, form-in-modal anatomy, and the full destructive modal pattern.
|
|
152
154
|
|
|
153
155
|
Declare all modals in the component JSX, controlled by a single `openModal`
|
|
154
156
|
state union:
|
|
@@ -190,38 +192,50 @@ Always equal columns (`template={[1, 1]}`), always collapse below desktop.
|
|
|
190
192
|
|
|
191
193
|
## Section 7 — Section cards
|
|
192
194
|
|
|
193
|
-
Each content section is wrapped in a `SectionCard
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
(not `@spark-web/section-card`). The API differs:
|
|
195
|
+
Each content section is wrapped in a `SectionCard` from
|
|
196
|
+
`@spark-web/section-card`, composed with `SectionHeader` from
|
|
197
|
+
`@spark-web/section-header` for the card header:
|
|
197
198
|
|
|
198
199
|
```tsx
|
|
199
|
-
import { SectionCard } from '@
|
|
200
|
+
import { SectionCard } from '@spark-web/section-card';
|
|
201
|
+
import { SectionHeader } from '@spark-web/section-header';
|
|
200
202
|
|
|
201
|
-
<SectionCard label="Section Title"
|
|
203
|
+
<SectionCard header={<SectionHeader label="Section Title" />}>
|
|
204
|
+
{/* section content */}
|
|
205
|
+
</SectionCard>;
|
|
202
206
|
```
|
|
203
207
|
|
|
204
|
-
| Prop | Type | Notes
|
|
205
|
-
| ---------- | ----------- |
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
208
|
+
| Prop | Type | Notes |
|
|
209
|
+
| ---------- | ----------- | ------------------------------------------------------- |
|
|
210
|
+
| `children` | `ReactNode` | Required — main content area |
|
|
211
|
+
| `header` | `ReactNode` | Optional — renders above the content; use SectionHeader |
|
|
212
|
+
| `footer` | `ReactNode` | Optional — rendered below a Divider |
|
|
213
|
+
|
|
214
|
+
The header text (`label`), optional `action`, and optional `controls` belong to
|
|
215
|
+
`SectionHeader` — see `node_modules/@spark-web/section-header/CLAUDE.md`.
|
|
209
216
|
|
|
210
217
|
Return `null` for sections conditionally hidden — never render an empty card.
|
|
211
218
|
|
|
219
|
+
Working in portal-hub? Apply the substitutions in
|
|
220
|
+
`node_modules/@spark-web/design-system/patterns/internal-admin/portal-hub.md`.
|
|
221
|
+
|
|
212
222
|
---
|
|
213
223
|
|
|
214
224
|
## Section 8 — Section data tables
|
|
215
225
|
|
|
216
|
-
See `
|
|
217
|
-
loading/empty state props.
|
|
226
|
+
See `node_modules/@spark-web/data-table/CLAUDE.md` for DataTable API, column
|
|
227
|
+
definitions, and loading/empty state props.
|
|
218
228
|
|
|
219
229
|
Detail-page-specific rules (differ from list pages):
|
|
220
230
|
|
|
221
231
|
- **`PAGE_SIZE = 5`** — always 5 items per section table (not 20 like list
|
|
222
232
|
pages)
|
|
223
233
|
- **Pagination threshold**: render `TablePagination` only when
|
|
224
|
-
`total > PAGE_SIZE`
|
|
234
|
+
`total > PAGE_SIZE`. `TablePagination` is NOT a spark-web component (COMPONENT
|
|
235
|
+
GAP) — build a placeholder from `@spark-web/box` + `@spark-web/button`
|
|
236
|
+
(prev/next + "Show N of M") and flag it for product design review before
|
|
237
|
+
production. Props: `total`, `pageSize`, `current`, `dataShowing`,
|
|
238
|
+
`onChange(page)`
|
|
225
239
|
- **Reset page**: reset to 1 when the record context changes (e.g. `userId`)
|
|
226
240
|
|
|
227
241
|
```tsx
|
|
@@ -255,6 +269,7 @@ const pageItems = data?.items ?? [];
|
|
|
255
269
|
</Text>
|
|
256
270
|
}
|
|
257
271
|
/>
|
|
272
|
+
{/* COMPONENT GAP: TablePagination — see the pagination rules above */}
|
|
258
273
|
{total > PAGE_SIZE && (
|
|
259
274
|
<TablePagination
|
|
260
275
|
total={total}
|
|
@@ -271,8 +286,9 @@ const pageItems = data?.items ?? [];
|
|
|
271
286
|
|
|
272
287
|
## Section 9 — Tabbed sections
|
|
273
288
|
|
|
274
|
-
See `
|
|
275
|
-
required internal-admin background override, and the null
|
|
289
|
+
See `node_modules/@spark-web/tabs/CLAUDE.md` for the Tabs API, dynamic tab
|
|
290
|
+
construction, the required internal-admin background override, and the null
|
|
291
|
+
guard pattern.
|
|
276
292
|
|
|
277
293
|
Use tabs when a section has multiple sub-views (e.g. Email / SMS history). Each
|
|
278
294
|
tab panel follows the same PAGE_SIZE=5 and pagination rules as Section 8.
|
|
@@ -300,7 +316,7 @@ tab panel follows the same PAGE_SIZE=5 and pagination rules as Section 8.
|
|
|
300
316
|
<Badge tone={statusTone}>{statusLabel}</Badge>
|
|
301
317
|
</Box>
|
|
302
318
|
{actions.length > 0 && (
|
|
303
|
-
<Box
|
|
319
|
+
<Box css={{ minWidth: 130 }}>
|
|
304
320
|
<ActionDropdown label="Actions" actions={actions} />
|
|
305
321
|
</Box>
|
|
306
322
|
)}
|
|
@@ -329,10 +345,14 @@ tab panel follows the same PAGE_SIZE=5 and pagination rules as Section 8.
|
|
|
329
345
|
{/* Content */}
|
|
330
346
|
<Columns gap="xlarge" template={[1, 1]} collapseBelow="desktop">
|
|
331
347
|
<Stack gap="xlarge">
|
|
332
|
-
<SectionCard label="Details"
|
|
348
|
+
<SectionCard header={<SectionHeader label="Details" />}>
|
|
349
|
+
{/* fields */}
|
|
350
|
+
</SectionCard>
|
|
333
351
|
</Stack>
|
|
334
352
|
<Stack gap="xlarge">
|
|
335
|
-
<SectionCard label="History"
|
|
353
|
+
<SectionCard header={<SectionHeader label="History" />}>
|
|
354
|
+
{/* table + pagination */}
|
|
355
|
+
</SectionCard>
|
|
336
356
|
</Stack>
|
|
337
357
|
</Columns>
|
|
338
358
|
</Stack>
|
|
@@ -340,6 +360,17 @@ tab panel follows the same PAGE_SIZE=5 and pagination rules as Section 8.
|
|
|
340
360
|
|
|
341
361
|
---
|
|
342
362
|
|
|
363
|
+
## Documented exceptions summary
|
|
364
|
+
|
|
365
|
+
These raw CSS values are required and have no Spark token equivalent. Use them
|
|
366
|
+
exactly as written.
|
|
367
|
+
|
|
368
|
+
| Value | Property | Reason |
|
|
369
|
+
| --------------- | ---------------------------- | -------------------------------------------------------------------- |
|
|
370
|
+
| `minWidth: 130` | ActionDropdown container Box | Prevents dropdown collapse on narrow content; no Spark minWidth prop |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
343
374
|
## Do NOTs
|
|
344
375
|
|
|
345
376
|
- NEVER apply list-page spacing to a detail page — outer wrapper uses
|
|
@@ -347,12 +378,44 @@ tab panel follows the same PAGE_SIZE=5 and pagination rules as Section 8.
|
|
|
347
378
|
- NEVER place a destructive action before non-destructive actions in the
|
|
348
379
|
dropdown
|
|
349
380
|
- NEVER call a destructive mutation directly from a dropdown item — open a modal
|
|
350
|
-
- NEVER surface modal errors as page-level Alerts — see
|
|
381
|
+
- NEVER surface modal errors as page-level Alerts — see
|
|
382
|
+
`node_modules/@spark-web/modal-dialog/CLAUDE.md`
|
|
351
383
|
- NEVER use `PAGE_SIZE = 20` on section tables — always 5 on detail pages
|
|
352
384
|
- NEVER render `TablePagination` when `total <= PAGE_SIZE`
|
|
353
385
|
- NEVER render an empty `SectionCard` for hidden sections — return `null`
|
|
354
386
|
- NEVER render `ActionDropdown` when `actions` is empty — gate with
|
|
355
387
|
`actions.length > 0`
|
|
356
388
|
- NEVER render `Tabs` inside `SectionCard` without the background override — see
|
|
357
|
-
`tabs/CLAUDE.md`
|
|
389
|
+
`node_modules/@spark-web/tabs/CLAUDE.md`
|
|
358
390
|
- NEVER use `Container` as the outer page wrapper
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Validation checklist
|
|
395
|
+
|
|
396
|
+
Run before marking any detail-page task complete and fix every violation; the
|
|
397
|
+
uplift protocol in `node_modules/@spark-web/design-system/CLAUDE.md` runs this
|
|
398
|
+
list PASS/FAIL against existing pages.
|
|
399
|
+
|
|
400
|
+
1. Outer wrapper is
|
|
401
|
+
`Stack height="full" paddingX="xlarge" paddingY="xxlarge" gap="xlarge"` — not
|
|
402
|
+
list-page spacing, not Container.
|
|
403
|
+
2. Header: `Heading level="1"` first, `Badge` after it; ActionDropdown only when
|
|
404
|
+
`actions.length > 0`; no inline action buttons in the header.
|
|
405
|
+
3. Dropdown action order: non-destructive → restore-type → critical destructive
|
|
406
|
+
last; permanently unavailable actions hidden, temporarily unavailable actions
|
|
407
|
+
disabled.
|
|
408
|
+
4. Destructive actions open a ContentDialog modal; direct actions surface
|
|
409
|
+
feedback via the page-level Alert between header and content — modal errors
|
|
410
|
+
render inside the modal, never as page-level Alerts.
|
|
411
|
+
5. All modals declared in JSX, controlled by a single `openModal` union state.
|
|
412
|
+
6. Content is `Columns template={[1, 1]} gap="xlarge" collapseBelow="desktop"`.
|
|
413
|
+
7. Every content section is wrapped in a SectionCard (or the documented
|
|
414
|
+
consumer-overlay equivalent); conditionally hidden sections return `null`.
|
|
415
|
+
8. Section tables use `PAGE_SIZE = 5`; pagination only when `total > PAGE_SIZE`;
|
|
416
|
+
page resets when the record context changes.
|
|
417
|
+
9. Tabs inside SectionCard use the internal-admin background override per
|
|
418
|
+
`node_modules/@spark-web/tabs/CLAUDE.md`.
|
|
419
|
+
10. No raw CSS beyond the Documented exceptions table; every component is
|
|
420
|
+
`@spark-web/*` or an explicit consumer-overlay substitute; gaps flagged with
|
|
421
|
+
`// COMPONENT GAP:`.
|