Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Dependencies and generated application output
node_modules/
bun.lock
out/
dist/
release/
Expand Down
12 changes: 6 additions & 6 deletions docs/UI_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ This contract preserves the approved MVP concept and prevents feature ownership

- Clicking a provider opens a Focus Card for that provider. The provider is fixed; there is no second provider selector.
- The Focus Card contains only the provider mark, project folder, Normal/YOLO profile, launch action, and contextual danger confirmation.
- Settings uses a top section strip: General, Appearance, Controls, Browser, and Plugins. General owns language. Appearance owns palette, background pattern, the shortcut-hint toggle, system HOME tiles, and the HOME editor entry. Controls owns click focus, hover focus, window snapping, edge panning, zoom sensitivity, wheel direction, and keyboard shortcuts. Browser owns agent access, agent-indicator visibility, tab restore, downloads, redacted activity, and browser-data clearing. Plugins owns install preview, permission review, the installed-plugin list, enable/disable/uninstall, and contribution actions. Media controls never appear there.
- Settings uses a top section strip: General, Appearance, Controls, Browser, and Plugins. General owns language. Appearance owns palette, background pattern, the shortcut-hint toggle, system HOME tiles, and the HOME editor entry. Controls owns click focus, hover focus, window snapping, edge panning, zoom sensitivity, wheel direction, ordinary scroll pan/zoom, the Off/On/Key wheel/pinch capture mode, the full canvas navigation override, and action shortcuts. Browser owns agent access, agent-indicator visibility, tab restore, downloads, redacted activity, and browser-data clearing. Plugins owns install preview, permission review, the installed-plugin list, enable/disable/uninstall, and contribution actions. Media controls never appear there.
- Click focus has three explicit modes: Off, Single click, and Double click. It is off by default. Selection and its visible outline still work when camera focus is off; a double-click mode never jumps the camera on the first click.
- Selection is exclusive across terminals and the built-in Browser: pressing on empty canvas clears it. The selected live surface holds keyboard focus and loses it on deselect.
- Hover focus is a separate off-by-default selection mode: after a configurable delay (slow `500ms`, normal `250ms`, fast `80ms`) the terminal or built-in Browser under the pointer becomes selected and receives keyboard focus; leaving the card clears the selection after the same delay.
- Selection is currently exclusive across terminals and the built-in Browser: pressing on empty canvas clears it. Input focus is tracked independently so future multi-selection does not have to redefine wheel ownership.
- Hover focus is an off-by-default input-focus mode. After a configurable delay (slow `500ms`, normal `250ms`, fast `80ms`), an input-bearing widget under the pointer receives logical focus without changing selection; terminal and native Browser keyboard input follows that focus. Pointer leave only cancels a pending transfer; assigned focus remains until another focusable widget is clicked/hovered or the user clicks outside every widget. Focusable surfaces are terminals, the native Browser, plugin iframe/canvas surfaces, and actually scrollable HOME lists; decorative and action-only tiles do not take focus.
- Keyboard shortcuts are user-remappable and persisted locally. Defaults are `Home` for focusing the Home zone and `F2` for renaming the selected terminal window. Rename is an inline header edit and does not recreate the PTY. A compact passive hint in the canvas bottom-right reflects the persisted bindings immediately and can be hidden from Appearance.
- Snapping is enabled by default and can be disabled without changing existing window bounds. Edge panning remains off by default and exposes slow/normal/fast speed. Wheel direction is configurable separately for terminal scrolling and camera zoom. By default, wheel-down scrolls a live terminal down, while camera zoom preserves the original CanvasTTY direction.
- Snapping is enabled by default and can be disabled without changing existing window bounds. Edge panning remains off by default and exposes slow/normal/fast speed. Wheel direction is configurable separately for terminal scrolling and canvas navigation; canvas inversion applies to both pan axes and historical wheel zoom. Fresh profiles pan on ordinary scroll, while migrated profiles retain ordinary wheel zoom, direction, and sensitivity.

## Visual system

Expand All @@ -35,14 +35,14 @@ This contract preserves the approved MVP concept and prevents feature ownership
- Terminal cards keep a `54px` header. At normal scale the header shows the provider mark and terminal working directory until the user explicitly renames the window; a custom title then replaces the path. Close remains visible at the far right; canvas cards do not expose maximize/fullscreen. There is no lifecycle dot in terminal chrome.
- After a provider PTY exits, its terminal card exposes restart in the same session with a header action and `Ctrl+D`. Restart preserves the card, title, bounds, scrollback, and xterm instance while issuing a fresh provider process and browser capability.
- Terminal cards switch to semantic summary mode below `0.5×`. Summary typography counter-scales as the camera moves farther out so identical cards keep the same readable hierarchy instead of exposing tiny xterm text.
- In semantic summary mode a card is a canvas navigation target: wheel input zooms the camera around it, and clicking the summary always selects it with a visible card outline. Camera focus follows only the configured Off/Single click/Double click mode. At normal scale the live terminal regains wheel ownership.
- In semantic summary mode, clicking a card still selects it with a visible outline and camera focus follows only the configured Off/Single click/Double click mode. Renderer, xterm, and plugin cards follow the same wheel focus matrix as normal scale: only a focused input-bearing card can keep wheel in Off or released-Key mode; On, an active Key binding, or the held full navigation override gives it to the canvas. A Browser summary or other non-native placeholder is always canvas-owned for wheel/pinch.
- Every terminal edge and corner is a resize target. The minimum card size is `420 × 260`; resizing updates the xterm viewport and preserves the opposite edge.
- Live terminal selection follows the visible pointer position at every canvas zoom. With a non-empty selection, `Ctrl+C`/`Ctrl+Shift+C` (or `Cmd+C`) copies it; `Ctrl+Shift+V`/`Cmd+V` and `Shift+Insert` paste from the system clipboard. Plain `Ctrl+C` without a selection remains the PTY interrupt. `Shift+Enter` sends a line-break sequence (`ESC [ 13 ; 2 u`) to the PTY instead of submitting the line.
- Canvas plugin apps use the same movable card grammar, `54px` header, resize/snap behavior, and semantic summary below `0.5×`. A `window` contribution opens a separate CanvasTTY-owned sandboxed window; arbitrary native window embedding is not part of the contract.
- The built-in Browser is one movable, resizable core canvas card, not a plugin contribution. It uses the same `54px` outer window header as other canvas cards, with its identity and hide-card action isolated from the internal tab strip below. Its trusted DOM chrome owns compact tabs/favicons, address/search, back/forward/reload, downloads, per-tab provider badges, site dialogs, and explicit Close tab/Close all. Hiding the card keeps its tabs and shared authenticated Chromium profile alive. Below `0.5×`, during Edit HOME, and behind trusted dialogs/popovers, the native page is hidden and replaced with a stable semantic surface. During card or camera motion it remains live and follows frame-coalesced viewport geometry.
- An authenticated connection or heartbeat alone never shows agent presence. A branded badge appears only after that agent actually issues a browser command, and its cursor appears only after a real pointer position exists. Claude uses `#D97757`, Codex `#10A37F`, Kimi `#7C5CFC`, and an unknown provider `#7A8291`. Browser Settings separately controls indicator visibility without revoking browser access; the agent-access kill switch revokes the connection itself.
- With window snapping enabled, drag and resize use a hidden `10px` grid and a `10px` magnetic threshold for neighboring edges, centers, and a consistent `20px` gap.
- Wheel input belongs to the surface under the pointer when that surface actually scrolls or consumes wheel input. Fresh profiles route wheel input over terminal and native Browser surfaces to the camera so a large card cannot trap canvas navigation; Controls → Zoom over applications can restore local application wheel ownership. The session list keeps local ownership. Passive Home widgets — limits, clock, media, and launcher tiles — allow camera zoom so Home does not shrink the usable zoom area.
- Empty-canvas drag always pans. On fresh profiles ordinary scroll over empty canvas pans on both axes; pinch and `Cmd/Ctrl + scroll` zoom around the pointer. **Use scroll wheel to zoom** restores historical ordinary-wheel zoom and is enabled by migration for existing profiles. Only a focused input widget interrupts canvas wheel/pinch; unfocused or non-focusable widgets leave those events to the canvas. **Wheel/pinch capture over widgets** has Off, On, and Key modes: Off preserves focused-widget ownership, On always transfers only wheel/pinch to the canvas, and Key transfers only wheel/pinch while its binding is held. A focused live Browser page therefore scrolls normally in Off or released-Key mode; unfocused Browser content, On, an active Key binding, the full override, pinch, and `Cmd/Ctrl + scroll` are canvas-owned. The owner selected for a Browser wheel sequence is held until 250 ms of wheel inactivity. Browser summaries and placeholders are always canvas-owned. Fresh profiles use Key with `Command` on macOS or `Ctrl` elsewhere. A separate configurable **Canvas navigation override** (default `Option` on macOS and `Alt` elsewhere) transfers wheel/pinch and drag while held; standalone Command/Ctrl is valid. While full override is held all canvas surfaces show `grab`; an owned drag shows `grabbing` until pointer up/cancel even after the binding is released.
- The canvas edge-pans RTS-style while the pointer rests within `56px` of a viewport edge over empty canvas; speed ramps linearly up to `900px/s` at the edge itself. Edge panning is off by default and enabled in Settings. Motion pauses over interactive surfaces (terminal cards, Home, controls) and while drag-panning.
- Dialog close actions stay inside their own header/control row with a consistent inset; they never overlap a field, outline, or panel boundary.

Expand Down
Loading