- 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
5.8 KiB
5.8 KiB
Detail Window Feature Specification
Overview
A detail window shows one view (YAML / Describe / Logs / Shell) for one Kubernetes object. Windows are grouped into krates and can be resized/moved within their container.
Core Responsibilities
- Display object data in one of four view types
- Allow window dragging within krate
- Support window resizing with proportional sibling adjustment
- Implement maximize/restore functionality
- Route keyboard focus on mouse-over
Window Types
Detail View (default)
- Purpose: Display static object information
- Content types: YAML, Describe, Logs (for pods/workloads)
Collection Window
- Purpose: List/Tree view of multiple objects
- Special features: Filter input, selection highlighting, view shortcuts
Window anatomy (380×362px default)
Header (36px height)
- Left: Shape glyph (8px, color-coded by object type)
- Middle: View label (uppercase, accent-colored) + object name + status badge
- Right: × button (close window)
- Cursor:
grab— drag to reposition within canvas - Double-click header: Maximize / restore window
- Drag: Move window within krate
Tab Bar
- Tabs: YAML · Describe · Logs · Shell
- Shell tab: disabled (opacity 0.45) for non-exec object types
- Active tab: accent underline/highlight
- Click tab: Switch view content
Content Area (286px height)
- Element:
<pre>(preformatted text) - Styling:
overflow: autoheight: 286pxfont-family: 'IBM Plex Mono'font-size: 12pxline-height: 1.65
- Scrollbar:
- Width: 8px
- Color: rgba(140,165,200,.18)
Resize Behavior
Resize Handle
- Positioned at bottom-right corner
- Drag to resize
- Proportional adjustment: When one window resized, siblings in same column/row resize proportionally
- Storage: Use
rowHeightsandcolWidthsarrays per krate (future enhancement)
Window Grid
- Column pitch: 412px
- Row pitch: 416px
- Window default: 380×362px (leaves room for grip/padding)
Maximize Functionality
Maximize State
- Width:
viewport.width - 44px(22px margins) - Height:
viewport.height - topBarHeight(68px) - bottomBarHeight(66px) - Camera adjusted:
camX = 22 - krate.wx - window.dx,camY = 68 - krate.wy - window.dy,zoom = 1
Trigger
- Key:
z(when mouse is over window) - Mouse: Double-click header
- Restore: Same trigger again
Keyboard Focus Routing
Mouse-Over Detection
- Track
mouseenter/mouseleaveper window - Set
hoveredWindowIdref - Clear on
mouseleave
Key Event Routing
Global keydown handler with { capture: true }:
if (hoveredWindowId is shell) {
route keypress to shell
} else if (hoveredWindowId is collection) {
route keypress to filter input
} else {
let it fall through to canvas shortcuts
}
Shell Special Case
- Space character goes to terminal (NOT spotlight)
- Must distinguish between canvas space-pan and shell space-input
View-Specific Content
YAML View
- Display full object YAML
- Secret objects: Base64-decode all data values
- Show banner:
⊙ secret values auto-decoded - Security: Handle carefully, never log decoded values
Describe View
- Human-readable object description
- Formatted for readability
- All metadata sections included
Logs View
- Pods/workloads only
- Live-tailing: Stream via WebSocket
- Auto-scroll to bottom on new lines (unless user scrolled up)
- Color-code:
- ERROR:
#ef6f6f - WARN:
#e8b54a - INFO:
#b9c6d8
- ERROR:
Shell View
- Implementation: xterm.js (real terminal)
- Backend: WebSocket →
kubectl exec -it <pod> -n <ns> -- sh - Keyboard routing: Route keypresses to terminal, passthrough terminal output
- Scroll wheel: Scroll terminal content (NOT canvas pan)
- Ctrl/⌘+scroll: Zoom canvas (not terminal zoom)
Collection Window Specifics
Size
- Default: 540×480px (larger than detail windows)
Header
- Title:
pods · ns/payments - Status summary badges:
✓ N / ⚠ N / ✗ N - Filter input (auto-focused on open)
- List / Tree toggle buttons
- Keyboard hint:
↑↓ ⌥L/S/D/Y
List Mode
- Rows: shape glyph + name + health metric + type badge + view buttons + status dot
- Selected row:
background: accentDim; border-left: 2px solid accent - Hover row:
background: rgba(255,255,255,.04) - Sorted: degraded/failed first, then pending, then ready; alpha within groups
Tree Mode (k9s xray)
- Workloads expand to show pods
- Pods expand to show configMaps, secrets, PVCs
- Services/ingresses expand to show targets
- Relation tags:
pod,configMap,secret,volume,selects,routes,used by - Indent:
20px * depth - Filtering: Keep matching nodes + all ancestors for hierarchy
Window State
interface Window {
wid: string; // unique window ID
kind: 'detail' | 'collection';
tab: 'logs' | 'shell' | 'describe' | 'yaml';
dx: number; // offset within krate (column * 412)
dy: number; // offset within krate (row * 416)
w: number; // width
h: number; // height
isMaximized: boolean; // current state
prevW?: number; // previous width (for restore)
prevH?: number; // previous height (for restore)
}
Gotchas
- Space key: Must distinguish between canvas space-pan (capture with
{ capture: true }) and shell space-input - Ctrl/⌘+scroll: Use
{ capture: true }on canvas to intercept before window scroll containers - Secret decoding: Do server-side or careful client-side; never log decoded values
- Window resizing: Proportional siblings requires storing
rowHeights/colWidthsarrays (not just individualdx/dy) - Focus routing: Mouse-over + type should focus shell/filter, not trigger canvas shortcuts
- Collection auto-focus: On creation, focus filter input in next tick using ref +
useEffect