---
phase: 37
slug: admin-global-item-management
status: approved
shadcn_initialized: false
preset: none
created: 2026-04-19
reviewed_at: 2026-04-19
---
# Phase 37 — UI Design Contract
> Visual and interaction contract for Admin — Global Item Management. Generated from CONTEXT.md decisions, RESEARCH.md findings, and codebase pattern analysis.
---
## Design System
| Property | Value |
|----------|-------|
| Tool | none — Tailwind CSS v4 utility-first |
| Preset | not applicable |
| Component library | none (custom components) |
| Icon library | LucideIcon from `src/client/lib/iconData` |
| Font | System default (Inter-like sans-serif via browser) |
No `components.json` detected. No shadcn. All styling is plain Tailwind utility classes matching the app's existing light/airy aesthetic.
---
## Spacing Scale
Standard 8-point scale from existing app patterns:
| Token | Value | Usage |
|-------|-------|-------|
| xs | 4px (`gap-1`, `p-1`) | Icon gaps, inline chip gaps |
| sm | 8px (`gap-2`, `p-2`) | Compact table cell padding, tag chips |
| md | 16px (`gap-4`, `p-4`) | Default form field spacing, sidebar padding |
| lg | 24px (`gap-6`, `p-6`) | Section padding, edit page padding |
| xl | 32px (`gap-8`, `p-8`) | Page-level layout gaps |
| 2xl | 48px | Major section breaks (used sparingly) |
| 3xl | 64px | Not used in admin panel |
Exceptions:
- Table row height: `py-3` (12px vertical) + `px-4` (16px horizontal) for dense data rows
- Sidebar nav items: `px-3 py-2` (12px vertical) — matches Phase 36 admin shell
---
## Typography
Matches existing app type scale. No new sizes introduced.
| Role | Size | Weight | Line Height | Tailwind |
|------|------|--------|-------------|---------|
| Body / table cell | 14px | 400 | 1.5 | `text-sm` |
| Label / column header | 12px | 600 | 1.4 | `text-xs font-semibold` |
| Form field label | 14px | 600 | 1.4 | `text-sm font-semibold` |
| Page heading | 18px | 600 | 1.3 | `text-lg font-semibold` |
Weights used: 400 (regular) + 600 (semibold). No medium (500), no bold (700).
---
## Color
60/30/10 rule — matches Phase 36 admin shell exactly:
| Role | Value | Tailwind | Usage |
|------|-------|---------|-------|
| Dominant (60%) | #ffffff | `bg-white` | Page backgrounds, table rows, edit form |
| Secondary (30%) | #f9fafb | `bg-gray-50` | Main content area, input backgrounds |
| Border / divider | #f3f4f6 | `border-gray-100` | Table row dividers, sidebar border |
| Text primary | #111827 | `text-gray-900` | Item names, column data |
| Text secondary | #4b5563 | `text-gray-600` | Labels, form hints |
| Text muted | #9ca3af | `text-gray-400` | Column headers, disabled states |
| Accent (10%) | #2563eb | `text-blue-600`, `bg-blue-50` | Save button, active nav link indicator |
| Destructive | #dc2626 | `bg-red-600 hover:bg-red-700` | Delete button ONLY |
Accent reserved for:
- Save/Update primary button
- Active sidebar nav link highlight (left border or background)
Destructive reserved for:
- Delete button in edit page
- Confirm delete button inside the delete dialog
---
## Component Inventory
### Admin Items List (`/admin/items`)
**Layout:**
```
┌─────────────────────────────────────────────────┐
│ Heading: "Catalog Items" [search input] │
│ Tag filter chips │
│ "1,247 items" count label │
├──────┬────────────┬─────┬───────┬───────┬───────┤
│ Brand+Model │ Category │ Wt │ Price │ Tags │ Owners│
├──────┴────────────┴─────┴───────┴───────┴───────┤
│ row row row ... (50 per page) │
│ [sentinel div — triggers next page] │
└─────────────────────────────────────────────────┘
```
**Table element specs:**
- Wrapper: `w-full overflow-hidden rounded-xl border border-gray-100 bg-white`
- `
`: `w-full text-sm`
- ``: `bg-gray-50 border-b border-gray-100`
- Column header cells: `px-4 py-3 text-left text-xs font-semibold text-gray-400 uppercase tracking-wide`
- `` rows: `border-b border-gray-50 hover:bg-gray-50 cursor-pointer transition-colors`
- Body cells: `px-4 py-3 text-sm text-gray-700`
- Brand+Model cell: bold brand (`font-medium text-gray-900`) + muted model (`text-gray-500`)
**Tags column:**
- ≤ 2 tags: render as inline chips — `text-xs bg-gray-100 text-gray-500 px-2 py-0.5 rounded-full`
- > 2 tags: render count badge — `text-xs bg-gray-100 text-gray-500 px-2 py-0.5 rounded-full` displaying "+N"
**Owner count column:**
- Numeric, right-aligned, `text-gray-500`
- 0 owners: `text-gray-300`
**Search input:**
- `rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-300`
- Placeholder: "Search catalog..."
- Width: `w-64`
**Tag filter:**
- Row of clickable chips below search bar
- Selected: `bg-blue-50 text-blue-600 border border-blue-200`
- Unselected: `bg-gray-100 text-gray-600`
- Multi-select allowed (matches existing CatalogSearchOverlay pattern)
**Infinite scroll sentinel:**
- `` at bottom of table
- IntersectionObserver triggers `fetchNextPage()` when sentinel enters viewport
- Loading indicator: `Loading...
`
### Admin Items Edit Page (`/admin/items/$itemId`)
**Layout:**
```
← Items (back link)
Salsa Woodsmoke 700 (page heading: brand + model)
3 users in collection (owner count subtext)
┌──────────────────────────────────────────────────┐
│ [Image preview — GearImage] │
│ [Image URL input] │
├──────────────────────────────────────────────────┤
│ Brand (Manufacturer) [dropdown] │
│ Model [text input] │
│ Category [text input] │
├──────────────────────────────────────────────────┤
│ Weight (g) [number input] │
│ Price (€) [number input] │
├──────────────────────────────────────────────────┤
│ Tags [chip input] │
│ Description [textarea] │
│ Source URL [url input] │
│ Image Credit [text input] │
│ Image Source URL [url input] │
├──────────────────────────────────────────────────┤
│ [Save Changes] [Delete Item]│
└──────────────────────────────────────────────────┘
```
**Form wrapper:** `max-w-2xl mx-auto` (consistent with catalog detail page width)
**Field groups:** separated by `border-t border-gray-100 pt-6 mt-6`
**Input styles (all fields):**
- Text/number/url: `w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-300`
- Textarea: same + `min-h-[80px] resize-y`
- Manufacturer dropdown: `