Files
opencode-krates-connector/design/admin-drawer.md
Hermes Agent 89bc5e8c15 docs: Finalize all design documents
Signed-off-by: Hermes Agent <hermes@nosuchhost>
2026-06-16 09:00:33 -04:00

4.9 KiB

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

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

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)