# 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