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:
Hermes Agent
2026-06-16 08:32:47 -04:00
parent b31fa3cde5
commit 78f19cde7d
12 changed files with 2709 additions and 2 deletions

101
design/krate.md Normal file
View File

@@ -0,0 +1,101 @@
# Krate (Window Group) Feature Specification
## Overview
A krate is a named group of detail windows for a single Kubernetes object or collection. Krates live on the canvas and serve as organizational units for related workspace views.
## Core Responsibilities
- Group related windows together visually and logically
- Auto-fit frame around contained windows
- Manage window layout within krate boundaries
- Handle krate-level interactions (move, drag, collapse, expand)
## Visual Container
### Krate Frame
- **Dashed border**: `border: 1px dashed rgba(color, .3)`, `border-radius: 18px`
- **Background**: `rgba(color, .04)` (subtle color tint)
- **Auto-fit**: Frame adjusts to bounding box of all windows + 30px padding
- **Color**: Matches namespace palette (e.g., payments: `#6fb1ff`)
### Header Bar
Above the frame:
- Shows object name + status badge + window count
- **Drag handle**: Move entire krate
- **× button**: Dismiss krate
- **Minimize button** (`—`): Collapse to overview card
- **Double-click header**: Collapse/expand toggle
## Window Layout
### Grid System
- Windows tiled in 2-column grid
- Column 0: `dx: 0`
- Column 1: `dx: 412`
- Row height: 416px
- **Window default size**: 380×362px
### Properties
- Windows never overlap (snap-to-grid on release)
- When one window resized, siblings resize proportionally in same column/row
- Storage:
```typescript
interface Window {
wid: string;
kind: 'detail' | 'collection';
tab: 'logs' | 'shell' | 'describe' | 'yaml';
dx: number; // offset within krate (column * 412)
dy: number; // offset within krate (row * 416)
w: number;
h: number;
}
```
## Krate Interactions
### Dragging
- **Drag header** = move entire krate
- **Non-overlapping placement**: On drag release, nudge to avoid overlap with other krates
- **Gentle snap, not strict grid** (allows flexibility while preventing overlap)
### Collapse/Expand
- **Minimized state**: 230px-wide card showing:
- Name
- View-letter badges (Y/D/L/S)
- Status dot
- Window count
- Namespace
- **Double-click collapsed card**: Re-expand and fly camera to krate
### Camera Fly
- On krate creation: animate camera to center krate at `zoom: 0.92`
- Duration: `.52s cubic-bezier(.22,.8,.28,1)`
- Position: center of krate's bounding box
## Krate State
```typescript
interface Krate {
id: string;
objId: string | null; // null for collection krates
collScope?: { kind: 'namespace' | 'category', value: string };
label: string; // display name
status: string; // status badge text
color: string; // hex, from namespace palette
wx: number; wy: number; // world position (top-left of frame)
minimized: boolean;
windows: Window[];
seq: number; // for generating unique window IDs
}
```
## Non-Overlapping Placement Algorithm
1. Try computed default position
2. Check bounding boxes against all existing krates
3. If overlap, nudge by fixed increments (e.g., 20px right/down)
4. Repeat until no overlap
5. **Same algorithm** used on creation AND drag release
## Gotchas
1. **Auto-fit frame**: Re-compute bounding box whenever windows are added/removed/moved/resized
2. **Non-overlapping**: Use AABB (Axis-Aligned Bounding Box) collision detection
3. **Window grid**: Store `colWidths` and `rowHeights` arrays for proper resize relationships (future enhancement)
4. **Krate ID**: `objId` is null for collections; otherwise references the Kubernetes object ID