Files
opencode-krates-connector/design/canvas.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

106 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Canvas Feature Specification
## Overview
The canvas is the infinite zoomable/pannable workspace where krates live. It serves as the primary interaction surface for exploring Kubernetes clusters.
## Core Responsibilities
- Render an infinite 2D workspace (12000×8000px world)
- Handle camera navigation (pan/zoom)
- Manage Level of Detail (LOD) based on zoom level
- Display a CAD grid overlay
- Coordinate global interactions (space panning, spotlight trigger)
## Technical Requirements
### Viewport & World Layer
- Full viewport (`position: fixed; inset: 0`)
- Background color: `#0b0e13`
- World layer: 12000×8000px div transformed via `translate(camX, camY) scale(zoom)`
- All krates/windows are absolutely positioned children
### Grid Overlay (CSS background-image)
- Fine grid: 34px spacing, rgba(125,145,175,.04)
- Coarse grid: 170px spacing, rgba(125,145,175,.075)
- Both X and Y repeating linear gradients
### Camera State
```typescript
interface CanvasState {
camX: number; // world-to-screen X offset
camY: number; // world-to-screen Y offset
zoom: number; // 0.16 2.2; default 0.92
flying: boolean; // true during animated camera transitions
dragging: boolean; // true during pan drag
collapsed: boolean; // LOD: true when zoom < 0.4
spacePanning: boolean; // true while space is held
}
```
## Navigation
### Scroll Wheel
- ** Default **: Pan canvas
- ** Ctrl/⌘ + scroll **: Zoom canvas (intercepted via wheel event with `e.ctrlKey || e.metaKey`)
### Space + Drag Panning
- Critical: must work even when shell window has keyboard focus
- Implementation:
- `document.addEventListener('keydown', handler, { capture: true })` on space
- Set "panning" flag, prevent default on body
- Forward `mousemove` to canvas pan handler
- Release on `keyup` for space
- Do NOT use `e.stopPropagation()` - allow event propagation
### Click/Typed Key Triggers
- ** Click on empty canvas **: Open spotlight
- ** Type any key **: Open spotlight with that character pre-seeded
### Zoom Levels / LOD
- ** zoom > 0.5 **: Normal view — krates expanded, all windows visible, draggable
- ** zoom < 0.4 **: Collapsed view — krates become 230px wide overview cards, no windows rendered
- ** Hysteresis**: Collapse at 0.4, re-expand at 0.5 (prevents flickering)
### Animations
- CSS `transform` with `transition` only for programmatic "fly" animations: `.52s cubic-bezier(.22,.8,.28,1)`
- During user scroll/drag: `transition: none` for immediacy
## UI Components
### Top Bar
- Position: `absolute; top: 0; left: 0; right: 0; z-index: 10; height ~56px`
- Layout: `display: flex; align-items: center; padding: 13px 18px`
- Background: none (transparent)
- Left side: Logo pill, cluster pill, krate count pill
- Right side: Synced pill, admin button, roster avatars
### Bottom Hint Bar
- Position: `absolute; right: 18px; bottom: 18px`
- Shows keyboard hints (status bar)
### Zoom Pill
- Position: `absolute; left: 18px; bottom: 18px`
- Displays current zoom percentage
### Minimap
- Position: `absolute; right: 18px; bottom: 64px`
- Size: 180×120px
- Shows all krates as small rectangles
- Viewport indicator rectangle showing current view frustum
- Click anywhere to fly camera to that world position
## Interaction Summary
| Interaction | Behavior |
|---|---|
| Scroll wheel | Pan canvas |
| Ctrl/⌘ + scroll | Zoom canvas |
| Space + drag | Pan canvas (even over windows/shells) |
| Click empty canvas | Open spotlight |
| Type any key | Open spotlight pre-seeded |
| Minimap click | Fly camera to position |
## Gotchas
1. **Space pan over shells**: Must intercept with `{ capture: true }`, prevent default, but don't stop propagation
2. **Ctrl/⌘+scroll**: Use `{ capture: true }` on canvas wheel handler to intercept before window scroll containers
3. **Camera transitions**: Only animate during programmatic fly, not user gestures
4. **LOD state**: Use stable boolean `collapsed` in state, not derived from `zoom` on every render