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:
101
design/krate.md
Normal file
101
design/krate.md
Normal 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
|
||||
Reference in New Issue
Block a user