Files
opencode-krates-connector/design/collection-window.md
Hermes Agent 89bc5e8c15 docs: Finalize all design documents
Signed-off-by: Hermes Agent <hermes@nosuchhost>
2026-06-16 09:00:33 -04:00

6.9 KiB
Raw Blame History

Design Document: Collection Window Feature Specification

Overview

A collection window provides an overview of Kubernetes objects in a category (All Pods, All Services, etc.) or namespace. It supports both list and tree views with filtering and selection.

Default Size

  • Width: 540px
  • Height: 480px (larger than detail windows for better data visibility)

Header

Title

  • Format: pods · ns/payments or All Pods
  • Bold styling

Status Summary

  • Health badges: ✓ N / ⚠ N / ✗ N
  • Colors: OK=green, Warn=amber, Error=red
  • Order: Ready/Warn/Error counts

Filter Input

  • Auto-focused on open
  • Styling:
    • font-family: IBM Plex Mono
    • font-size: 12px
    • Placeholder: Filter...
  • Instant filtering (no debounce needed for <1000 items)

View Toggle

  • List mode button: list icon
  • Tree mode button: tree icon
  • Toggles between list and tree display
  • Keyboard shortcut: t or click toggle button

Keyboard Hint

  • Always visible, muted text: ↑↓ ⌥L/S/D/Y
  • Shows navigation + view shortcuts

List Mode

Row Structure

Each row displays:

  • Shape glyph (8px, color-coded by object type)
  • Name (primary text)
  • Relation tag (muted, for tree mode)
  • Health metric (icon or text)
  • Type badge (small, muted)
  • View buttons: ⌥L, ⌥S, ⌥D, ⌥Y (hover show tooltips)
  • Status dot (green/amber/red)

Selection

  • Selected row:
    • Background: accentDim (subtle accent color)
    • Left border: 2px solid accent
  • Hover row:
    • Background: rgba(255,255,255,.04)
    • Border-radius: 4px

Sorting

  1. Primary: Health status
    • Degraded/failed first
    • Then pending
    • Then ready/running
  2. Secondary: Alphabetical within each group

Tree Mode (k9s xray-style)

Hierarchy

  • Workloads expand to pods:
    • Deployment → pods
    • StatefulSet → pods
    • DaemonSet → pods
  • Pods expand to resources:
    • Pods show configMaps, secrets, PVCs
  • Services/Ingresses expand to targets:
    • Show selectors
    • Show endpoints

Relation Tags

Show as small icons or labels:

  • pod (attached to pod rows)
  • configMap (mounted volumes)
  • secret (mounted secrets)
  • volume (PVC)
  • selects (service → pods)
  • routes (ingress → service)
  • used by (reverse relationships)

Indentation

  • Per depth: 20px indentation
  • Connector: L-shaped border element (vertical + horizontal)
  • Visual hierarchy clear at a glance

Expand/Collapse

  • Click chevron/arrow: Toggle children
  • Double-click name: Toggle
  • Click anywhere else on row: Select row

Filtering in Tree Mode

  • Matching nodes + all their ancestors must stay visible
  • Ancestors shown even if not matching, but with different styling
  • Children hidden if no match
  • Preserves hierarchy readability

Keyboard Navigation

List/Tree Mode

Key Context Action
↑ / ↓ Collection focused Move row selection
PageUp / PageDown Collection focused Move selection by page
Home / End Collection focused First / last row
Enter Row selected Open default view for selected row
⌥L / ⌥S / ⌥D / ⌥Y Row selected Open view for selected row
Esc Filter focused Blur filter input
Esc Collection focused No-op (handle in krate)
t Anywhere Toggle list/tree view

Mouse + Type Routing

  • Mouse-over collection window + type = focus filter input
  • Similar to shell routing but for filter input
  • Use hoveredWindowId ref to determine routing

View Shortcuts

Key Mapping (All use ⌥ Alt)

  • ⌥L: Open logs view (if supported)
  • ⌥S: Open shell view (if supported)
  • ⌥D: Open describe view
  • ⌥Y: Open YAML view

Implementation

  • Event listener with event.code for layout safety
  • Open views in newly created krate (or existing if spotlight session)
  • Shell tab disabled for non-pod workloads (opacity 0.45)

View-Specific Content

Logs View (Pods/Workloads Only)

  • Streaming: WebSocket → kubectl logs --follow
  • Auto-scroll: To bottom unless user scrolled up
  • Color coding:
    • ERROR: #ef6f6f
    • WARN: #e8b54a
    • INFO: #b9c6d8
  • Timestamps: Optional toggle (hidden by default)

Shell View (Pods Only)

  • Implementation: xterm.js
  • Disabled: For non-pod workloads, show disabled (muted)
  • Cursor: Blinking block cursor
  • Key routing: Route to shell when collected window hovered

Describe View

  • Human-readable object description
  • All metadata sections
  • Formatted for easy scanning

YAML View

  • Full object YAML
  • Secrets: Decode data values
  • Banner: ⊙ secret values auto-decoded
  • Monospace font, line numbers optional

Filter Behavior

Instant Filtering

  • No debounce (fast for <1000 items)
  • Debounce if dataset grows: 16ms

Filter Logic

  • Case-insensitive substring match
  • Match against: name, labels, annotations, namespace
  • For tree mode: Match name only (not ancestors)

Clear Filter

  • Esc key (when filter focused)
  • Clear button (×) in input
  • Empty string clears filter

Keyboard Focus

  1. Click collection window + type = focus filter
  2. Click filter input = focus
  3. Click anywhere else = blur filter, focus canvas shortcuts

State Management

Per-Window State

interface CollectionState {
  wid: string;        // window ID
  search: string;     // filter text
  view: 'list' | 'tree';
  sel: number;        // selected row index
  expanded: Set<string>;  // tree expansion state (node IDs)
}

Data Loading

interface CollectionData {
  kind: string;              // 'Pod', 'Service', etc.
  namespace?: string;        // undefined for "All Pods"
  items: K8sObject[];
  filtered: K8sObject[];     // after filter
  treeData?: TreeNode[];     // tree mode intermediate
}

Tree Node Structure

interface TreeNode {
  id: string;               // unique within collection
  name: string;
  kind: string;             // 'Pod', 'Deployment', etc.
  obj: K8sObject | null;    // null for synthetic nodes (e.g., "pods")
  depth: number;
  parentId: string | null;
  children: string[];       // node IDs
  relation: string;         // 'pod', 'configMap', 'selects', etc.
  hasChildren: boolean;
}

Performance Considerations

Large Datasets

  • List virtualization: Only render visible rows (window height / row height)
  • Tree optimization: Lazy expand (fetch children on expand, not preload)
  • Filtering: Use efficient algorithms (no regex, simple string.match)

Updates

  • Throttle tree rebuild: 100ms
  • Only rebuild if filter or data changed
  • Keep expansion state on update (if node still exists)

Gotchas

  1. Tree expansion: Keep ancestors visible when filtering
  2. Auto-focus: Focus filter input on window open (use ref + useEffect)
  3. View shortcuts: Use event.code (layout-safe)
  4. Sorting priority: Health first, then alphabetical
  5. Shell vs other types: Disable shell tab for non-pod workloads
  6. Filter scope: In tree mode, filter only on names, not on ancestors