feat: Add comprehensive design documentation for Krates
- Canvas: Infinite zoomable workspace with LOD and navigation - Spotlight: Fuzzy search with type filters and view shortcuts - Krate: Window group container with non-overlapping placement - Detail Window: YAML/Describe/Logs/Shell views with maximize - Top Bar: Cluster info, user presence, admin toggle - Admin Drawer: Multi-user presence and spectate functionality - Minimap: Browse and navigate canvas overview - Collection Window: List/tree views with filtering and sorting - Shell/Logs: Real-time terminal and log streaming - Backend: Go service with K8s API, WebSocket handlers, CRDT sync - Architecture: Full project structure and tech stack
This commit is contained in:
188
design/admin-drawer.md
Normal file
188
design/admin-drawer.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# 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直径
|
||||
- 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)
|
||||
Reference in New Issue
Block a user