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

204 lines
5.2 KiB
Markdown

# Design Document: Spotlight Feature Specification
## Overview
Spotlight is the universal search and discovery interface that allows users to quickly find and create krates for Kubernetes resources. It's triggered by clicking the canvas or typing any character.
## Core Responsibilities
- Handle universal search across Kubernetes resources
- Support fuzzy matching of names, namespaces, labels
- Allow quick creation of krates from search results
- Support filtering by resource type
## Trigger
- **Click on empty canvas**: Open spotlight
- **Type any key**: Open spotlight with that character pre-seeded
- **Esc key**: Close spotlight
- **Spotlight open**: Prevent canvas shortcuts from triggering
## Spotlight Anatomy
### Search Input
- Position: Top of spotlight panel
- Auto-focused on open
- Placeholder: `Search...`
- Clear on Esc
- Debounced: 16ms for fuzzy search
### Filter Bar
- Location: Below search input
- Filter chips: All, Krates, Namespaces, Pods, Deployments, Services
- Click filter: Apply filter
- Click active filter: Clear filter
### Results List
- Position: Below filter bar
- Max height: ~400px
- Scrollable
- Results: Search results + quick actions
- Keyboard navigation: ↑↓ to navigate, Enter to select, Esc to close
### Results Item
Content per item:
- Shape glyph (8px, color-coded by type)
- Name (primary text)
- Type badge (muted color)
- Namespace (muted, optional)
- View shortcuts: `L`, `S`, `D`, `Y`
- Hover: Highlight, show view shortcut tooltips
## Search Implementation
### Fuzzy Algorithm
```typescript
function fuzzy(query: string, text: string): number {
// Prefer starts-with matches
if (text.toLowerCase().startsWith(query.toLowerCase())) {
return 1 - query.length / text.length
}
// Then scoring based on character matching
let score = 0
let queryIndex = 0
for (let i = 0; i < text.length && queryIndex < query.length; i++) {
if (text[i].toLowerCase() === query[queryIndex].toLowerCase()) {
score++
queryIndex++
}
}
return score / query.length
}
```
### Search Scope
- Namespaces
- Pods
- Deployments
- Services
- ConfigMaps
- Secrets
- Krates (created by user)
### Resource Discovery
1. Initial load: Fetch all resources from `/api/resources`
2. Real-time updates: WebSocket `/ws/watch` for changes
3. Local cache: Store in Zustand krateStore
4. Filtering: Apply fuzzy search + type filter
## Results Organization
### Search vs Quick Actions
- Search results: Resource matches (top section)
- Quick actions: Create new krate, open specific view (bottom section)
### Quick Actions
- `Create krate for ns/{namespace}`
- `All pods`
- `All services`
- `All deployments`
- `Search again for...`
## Keyboard Navigation
| Key | Context | Action |
|---|---|---|
| ↑ / ↓ | Spotlight open | Move selection |
| PageUp / PageDown | Spotlight open | Page navigation |
| Home / End | Spotlight open | First / last item |
| Enter | Item selected | Create krate / open resource |
| Esc | Spotlight open | Close spotlight |
| Space | Input focused | Search space character |
| Ctrl+K | Anywhere | Open spotlight |
| / | Anywhere | Open spotlight |
## View Shortcuts
All use **Option/Alt** key:
- `⌥L`: Open logs view (if supported)
- `⌥S`: Open shell view (if supported)
- `⌥D`: Open describe view
- `⌥Y`: Open YAML view
## Krate Creation Flow
1. User selects resource from spotlight
2. Create new krate with:
- Title: Resource name
- Color: Namespace color palette
- Position: Find non-overlapping location
- Windows: Create detail windows for selected views
3. Fly camera to new krate
4. Zoom to 0.92
## State Management
### Spotlight State
```typescript
interface SpotlightState {
open: boolean;
query: string;
filterType: string | null;
sel: number;
navigated: boolean;
}
type FilterType = 'all' | 'krate' | 'namespace' | 'pod' | 'deployment' | 'service'
```
### Search State
```typescript
interface SearchState {
results: SearchResult[];
loading: boolean;
error: string | null;
}
interface SearchResult {
id: string;
type: string;
name: string;
namespace?: string;
score: number;
icon: string;
}
```
## Visual Design
### Spotlight Panel
- Position: Fixed, centered horizontally at top of canvas
- Width: 600px
- Max height: 500px
- Background: `#1a1e26`
- Border: `1px solid rgba(140,165,200,0.18)`
- Border-radius: 12px
- Shadow: `0 10px 40px rgba(0,0,0,0.5)`
### Results Item
- Hover background: `rgba(255,255,255,0.04)`
- Selected: `accentDim` (subtle accent color)
- Left border: 2px solid accent when selected
- Padding: 8px 12px
- Font-size: 14px
### Color Palette (by namespace)
- `default`: `#6fb1ff`
- `kube-system`: `#9c88ff`
- `kube-public`: `#4dd6e8`
- Custom namespaces: Pick from palette
## Gotchas
1. **Space character**: When spotlight open, space goes to search (not canvas pan)
2. **Esc handling**: Must be handled in spotlight, not propagate to canvas
3. **Fuzzy search**: Use debounced search for large datasets
4. **Keyboard routing**: When spotlight open, route keys to spotlight, not canvas
5. **Focus management**: Auto-focus input, trap Tab cycle when open
6. **Selection reset**: Reset selection on query change
## Future Enhancements
- Quick pick recent resources
- Star/favorite resources
- Saved searches
- Search history
- Resource previews
- Multi-resource selection