Files
opencode-krates-connector/design/detail-window.md
Hermes Agent 78f19cde7d 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
2026-06-16 08:32:47 -04:00

5.8 KiB
Raw Blame History

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: auto
    • height: 286px
    • font-family: 'IBM Plex Mono'
    • font-size: 12px
    • line-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 rowHeights and colWidths arrays 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/mouseleave per window
  • Set hoveredWindowId ref
  • 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

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

  1. Space key: Must distinguish between canvas space-pan (capture with { capture: true }) and shell space-input
  2. Ctrl/⌘+scroll: Use { capture: true } on canvas to intercept before window scroll containers
  3. Secret decoding: Do server-side or careful client-side; never log decoded values
  4. Window resizing: Proportional siblings requires storing rowHeights/colWidths arrays (not just individual dx/dy)
  5. Focus routing: Mouse-over + type should focus shell/filter, not trigger canvas shortcuts
  6. Collection auto-focus: On creation, focus filter input in next tick using ref + useEffect