# Phase 36: Admin Role & Panel Foundation — UI Design Contract

**Phase:** 36 — Admin Role & Panel Foundation
**Created:** 2026-04-19
**Status:** Ready for planning

---

## Design Intent

The admin panel is a protected, minimal shell consistent with the app's existing light/airy aesthetic. It is not a distinct visual world — it reuses the same white background, gray borders, and sans-serif type as the rest of GearBox. The only indicator of admin context is the sidebar and a subtle "Admin" badge or heading.

---

## Layout

```
┌─────────────────────────────────────────────────────────┐
│ TopNav (existing — unchanged)                           │
├──────────────┬──────────────────────────────────────────┤
│ Sidebar      │ Main content area                        │
│ w-56         │ flex-1, min-h                            │
│ border-r     │                                          │
│              │ <Outlet /> (placeholder for now)         │
│ Admin        │                                          │
│ ──────────   │                                          │
│ □ Items      │                                          │
│ □ Tags       │                                          │
│              │                                          │
└──────────────┴──────────────────────────────────────────┘
```

---

## Component Specs

### Admin Shell (`src/client/routes/admin.tsx`)

**Outer wrapper:** `flex min-h-[calc(100vh-3.5rem)]` (full height minus TopNav 3.5rem/14)

**Sidebar:**
- `w-56 border-r border-gray-100 bg-white p-4 flex flex-col gap-1`
- Header: `text-xs font-semibold text-gray-400 uppercase tracking-wide mb-3` — "Admin"
- Nav items: `flex items-center gap-2 px-3 py-2 rounded-lg text-sm` (disabled state below)

**Main content:**
- `flex-1 p-6 bg-gray-50`
- Contains `<Outlet />`

### Sidebar Nav Items (Disabled / Coming Soon)

Both "Items" and "Tags" are disabled in this phase.

**Disabled item style:**
```
flex items-center gap-2 px-3 py-2 rounded-lg text-sm
text-gray-300 cursor-not-allowed
```

**Icon + label + badge:**
```tsx
<div className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-300 cursor-not-allowed">
  <LucideIcon name="package" size={16} />
  <span>Items</span>
  <span className="ml-auto text-xs bg-gray-100 text-gray-400 px-1.5 py-0.5 rounded">Soon</span>
</div>
```

Icons to use:
- Items → `"package"` (matches existing collection icon)
- Tags → `"tag"`

### Admin Index Placeholder (`src/client/routes/admin/index.tsx`)

Simple centered placeholder:
```tsx
<div className="flex flex-col items-center justify-center h-64 text-center">
  <LucideIcon name="shield" size={32} className="text-gray-300 mb-3" />
  <p className="text-sm text-gray-500">Admin Panel</p>
  <p className="text-xs text-gray-400 mt-1">Select a section from the sidebar</p>
</div>
```

### Admin Link in UserMenu

Position: before Profile link (top of menu).
Only rendered when `auth?.user?.isAdmin === true`.

```tsx
{auth?.user?.isAdmin && (
  <>
    <Link
      to="/admin"
      onClick={() => setOpen(false)}
      className="flex items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 transition-colors"
    >
      <LucideIcon name="shield" size={16} className="text-gray-400" />
      Admin
    </Link>
    <div className="border-t border-gray-100 my-1" />
  </>
)}
```

---

## Palette (existing conventions)

| Token | Value | Usage |
|-------|-------|-------|
| bg-white | #ffffff | Sidebar, TopNav |
| bg-gray-50 | #f9fafb | Page background, main content |
| border-gray-100 | #f3f4f6 | Sidebar border, dividers |
| text-gray-900 | #111827 | Active/primary text |
| text-gray-500 | #6b7280 | Secondary text |
| text-gray-300 | #d1d5db | Disabled items |
| text-gray-400 | #9ca3af | Icons, muted labels |

---

## Responsive

- Sidebar is always visible (no mobile collapse in this phase — admin is desktop-only usage)
- `hidden md:flex` wrapper if needed to keep mobile layout clean, but admin route is inherently desktop

## UI-SPEC COMPLETE
