- 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
150 lines
4.1 KiB
Markdown
150 lines
4.1 KiB
Markdown
# Minimap Feature Specification
|
||
|
||
## Overview
|
||
The minimap provides a bird's-eye overview of all krates' positions on the canvas. It allows navigation by clicking to fly the camera to any location.
|
||
|
||
## Position & Size
|
||
|
||
### Placement
|
||
- Position: `absolute; right: 18px; bottom: 64px` (above zoom pill)
|
||
- Size: 180×120px
|
||
- Z-index: Must be above canvas but below spotlight (z-index: 20-30 range)
|
||
|
||
### Background
|
||
- Base: `rgba(16,20,28,.97)`
|
||
- Border: `1px solid rgba(140,165,200,.2)`
|
||
- Border-radius: `4px`
|
||
- Padding: None (full content area)
|
||
|
||
## Viewport Indicator
|
||
|
||
### Rectangle
|
||
- Shows current camera view frustum
|
||
- Position: Relative to minimap content (proportionally mapped)
|
||
- Size: Proportional to zoom level
|
||
- Color: Accent (e.g., `#4dd6e8` cyan) with 40% opacity
|
||
- Stroke: Solid line, 1px
|
||
|
||
### Mapping
|
||
- World position (wx, wy) → Minimap coordinates
|
||
- Formula:
|
||
```
|
||
mx = (wx + camX) / zoom scaling factor
|
||
my = (wy + camY) / zoom scaling factor
|
||
```
|
||
- Zoom mapping: Larger viewport indicator = lower zoom level
|
||
|
||
## Krate Visualization
|
||
|
||
### Representation
|
||
- Each krate = small rectangle (8×6px default)
|
||
- Color: Matches krate's namespace color
|
||
- Position: Relative to minimap origin
|
||
- Scaled down: ~1/60th of world space
|
||
|
||
### Content
|
||
- Krate positions only (not internal windows)
|
||
- All active krates on canvas
|
||
- Update on: krate create, delete, move
|
||
|
||
### Performance Optimization
|
||
- Only render visible krates (cull distant ones)
|
||
- Batch updates (throttle minimap render)
|
||
- Use CSS transform, not re-layout
|
||
|
||
## Interaction
|
||
|
||
### Click Navigation
|
||
- Click anywhere → fly camera to world position
|
||
- Calculate world coordinates from click position:
|
||
```
|
||
worldX = (clickX / minimapWidth) * worldWidth - viewportWidth/2
|
||
worldY = (clickY / minimapHeight) * worldHeight - viewportHeight/2
|
||
```
|
||
- Animate camera fly: `.52s cubic-bezier(.22,.8,.28,1)`
|
||
- Zoom: Set to `0.92` or user's preferred zoom
|
||
|
||
### Hover Effects (Optional)
|
||
- Hover krate rectangle → highlight preview on canvas
|
||
- Show tooltip: krate name, window count
|
||
|
||
## Canvas Synchronization
|
||
|
||
### Updates Triggered By
|
||
1. New krate creation
|
||
2. Krate movement (drag)
|
||
3. Krate deletion
|
||
4. Canvas resize (re-calculate scale)
|
||
5. Camera change (update viewport indicator)
|
||
|
||
### Throttling
|
||
- Debounce minimap render: 100ms
|
||
- Don't update on every pixel of drag
|
||
- Batch: Collect all krate changes, render once
|
||
|
||
## Visual Styling
|
||
|
||
### Krate Rectangles
|
||
- Size: 8×6px (small but visible)
|
||
- Color: Krate's namespace color
|
||
- Fill: Solid
|
||
- Border: None (or very subtle: rgba(255,255,255,.1))
|
||
|
||
### Viewport Indicator
|
||
- Fill: None
|
||
- Stroke: `#4dd6e8` (accent), 1px
|
||
- Opacity: 0.4
|
||
- Rounded corners: 2px
|
||
|
||
### Background Patterns (Optional)
|
||
- Subtle grid overlay (same as main canvas, fainter)
|
||
- Stars or dots for visual interest
|
||
- Very low opacity: rgba(255,255,255,.05)
|
||
|
||
## Coordinate Mapping
|
||
|
||
### World to Minimap
|
||
```
|
||
minimapScale = minimapWidth / worldWidth (e.g., 180 / 12000 = 0.015)
|
||
minimapX = (worldX + camX) * minimapScale
|
||
minimapY = (worldY + camY) * minimapScale
|
||
```
|
||
|
||
### Minimap to World (for click)
|
||
```
|
||
worldX = (minimapX / minimapScale) - camX
|
||
worldY = (minimapY / minimapScale) - camY
|
||
```
|
||
|
||
### Viewport Rect
|
||
```
|
||
viewportWidthWorld = viewportWidth / zoom
|
||
viewportHeightWorld = viewportHeight / zoom
|
||
|
||
viewportMinimapX = (camX * minimapScale)
|
||
viewportMinimapY = (camY * minimapScale)
|
||
viewportMinimapW = (viewportWidthWorld * minimapScale)
|
||
viewportMinimapH = (viewportHeightWorld * minimapScale)
|
||
```
|
||
|
||
## Animation
|
||
|
||
### Camera Fly
|
||
- Duration: `.52s`
|
||
- Easing: `cubic-bezier(.22,.8,.28,1)`
|
||
- Target: Center minimap-clicked position
|
||
- Zoom: Set to `0.92` (or user preference)
|
||
|
||
### Smooth Updates
|
||
- Smooth viewport indicator movement: CSS transition
|
||
- Avoid jitter during drag
|
||
- Use `requestAnimationFrame` for updates
|
||
|
||
## Gotchas
|
||
1. **Coordinate precision**: Use floating-point for accurate mapping
|
||
2. **Zoom handling**: Viewport indicator must scale inversely with zoom
|
||
3. **Performance**: Minimap should never block main thread
|
||
4. **Culling**: Don't render krates far outside view
|
||
5. **Click handling**: Ensure click z-index > canvas but < spotlight
|
||
6. **Responsiveness**: Recalculate mapping on window resize
|