- 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
102 lines
3.4 KiB
Markdown
102 lines
3.4 KiB
Markdown
# 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
|