# Design Document: Admin Drawer Feature Specification

## Overview
The admin drawer is a right-side panel that displays all users connected to the current yard (shared cluster workspace). It enables administrators to see real-time user activity and spectate on other users' workspaces.

## Trigger

### Activation
- Button: `◉ admin` in top bar
- Toggle: Click to open/close
- Close on: clicking backdrop, pressing Esc

### Modal Overlay
- Backdrop: `rgba(7,9,13,.4)`
- Click backdrop: Close drawer
- Click outside: Close drawer

## Drawer Layout

### Container
- Width: 380px
- Position: `absolute; right: 0; top: 0; bottom: 0; z-index: 56`
- Background: `rgba(13,17,24,.98)`
- Border: `border-left: 1px solid rgba(140,165,200,.2)`
- Animation: Slide-in from right

### Content Structure
- Header (fixed, sticky)
- Scrollable user list
- Footer (optional, for actions)

## User Card Structure

For each connected user (including self):

### Avatar Section
- Circle: 40px diameter
- Background: User color from palette
- Content:
  - For self: `★` (star)
  - For others: 2-letter initials
- Hover: Show full name + status tooltip

### Identity
- Name (bold)
- Status:
  - Active: `active · ns/payments`
  - Idle: `idle 5m` (or `idle Nm`)

### Activity Info
- Current spotlight query (if open)
  - Display: `🔍 pods in payments`
  - "typing…" pulsing indicator (if currently typing)
- Krate count: `N krates open`

### Open Krate List
Collapsible section showing each active krate:
- Clickable row
- Content:
  - Krate name
  - View-letter badges: `Y`, `D`, `L`, `S`
  - Status dot (health indicator)
- **Spectate**: Click any krate row to:
  - Close admin panel
  - Fly camera to that krate
  - Zoom to center the krate at `zoom: 0.92`

### Self User Special Case
- Real-time state updates
- Shows actual spotlight query
- Lists user's actual open krates
- Updates as user interacts

## Real-Time Updates

### Presence Protocol
Each client publishes to awareness channel:
```
{
  userId: string,
  name: string,
  color: string,
  lastActive: timestamp,
  query: string | null,        // spotlight query
  krateIds: string[],          // list of open krate IDs
  cursor: { x, y } | null      // optional cursor position
}
```

### Update Frequency
- On connection/disconnection: immediate
- On spotlight open/close: immediate
- On krate create/delete: immediate
- Periodic heartbeat: every 5 seconds

## Keyboard Navigation

| Key | Context | Action |
|---|---|---|
| Esc | Admin drawer open | Close drawer |
| ↑ / ↓ | Drawer focused | Navigate user cards |
| Click user card | User list | Expand/collapse krate list |
| Click krate row | Krate list | Spectate (fly to krate) |
| Click backdrop | Anywhere | Close drawer |

## User Sorting
- Self user: Always first
- Active users: Ordered by last active (most recent first)
- Idle users: Ordered by last active
- Collapsed by default: Minimize height

## Visual Feedback

### Active/Idle Indicators
- Active: Solid color avatar, no dimming
- Idle: Dimmed avatar (80% opacity), `idle Nm` label

### Typing Indicator
- Text: `typing…`
- Color: Muted accent
- Animation: Pulsing opacity or small bounce
- Show when user has spotlight open AND hasn't typed in <1s

### Status Dots
- Krate status: Green/amber/red dot (matching window content)
- Pod status dot: Already in krate view (reuse same color logic)

## Admin Features (Optional Future)

### Control Actions
- Notify user: Send notification to specific user
- Suspend: Temporarily disconnect user (for debugging)
- View logs: See admin-level logs per user

### Spectate Controls
- Step forward/backward: Next/previous krate
- Cycle through users: Left/right arrow
- Lock view: Prevent camera from moving (spectator mode)

## State Management

### Drawer State
```typescript
interface AdminState {
  open: boolean;
  users: {
    id: string;
    name: string;
    color: string;
    self: boolean;
    status: 'active' | 'idle';
    idleMinutes?: number;
    query?: string;
    typing: boolean;
    krateIds: string[];
  }[];
  focusedUserId: string | null;
}
```

### User State
```typescript
interface UserPresence {
  userId: string;
  name: string;
  color: string;
  lastActive: number;          // timestamp
  lastTyping: number;          // timestamp
  spotlightQuery: string | null;
  openKrates: KratePresence[];
}

interface KratePresence {
  krateId: string;
  label: string;
  viewCount: number;
  views: string[];             // ['Y', 'D', 'L', 'S']
  status: string;              // from first window
}
```

## Gotchas
1. **Self-updates**: User's own card must show real-time state, not cached data
2. **Focus management**: Keep focus on drawer when open, trap Tab cycle
3. **Idle detection**: 60 seconds of no activity = idle
4. **Typing indicator**: Debounce by 1000ms after last keypress
5. **Spectate behavior**: Close admin panel first, THEN fly camera
6. **Roster overflow**: Handle >10 users gracefully (scroll, paginate, or truncate)
