Skip to content

feat(layouts): saved layouts manager with Spotlight-style UI#4

Merged
PaulHorn merged 5 commits into
mainfrom
feat/saved-layouts-manager
Apr 20, 2026
Merged

feat(layouts): saved layouts manager with Spotlight-style UI#4
PaulHorn merged 5 commits into
mainfrom
feat/saved-layouts-manager

Conversation

@PaulHorn
Copy link
Copy Markdown
Contributor

Summary

  • Replace the window.prompt/alert-based save/load palette commands with a proper Saved Layouts modal. Lists existing layouts alphabetically, saves the current canvas arrangement (nodes + regions + zoom + viewport) under a name, loads / deletes with proper validation and error states. Reuses the existing layoutSave/List/Load/Delete IPC surface — no backend changes.
  • Drop the legacy Export Workspace Layout (native save dialog) and Import Workspace Layout (window.prompt) palette commands — superseded by the in-app modal per user request ("save layout with name in app not external").
  • Restyle the command palette to match the Cmd+Shift+F search overlay: rounded-3xl, white/20 outline, backdrop blur, leading magnifying-glass icon, bolder text, type-tinted circular icon tiles on rows, inset selection highlight. Three overlays (search / palette / layouts) now share one visual language.
  • Fix the stale "Toggle File Explorer" shortcut hint — was advertising ⌘⇧F, now shows ⌘⇧X after the collision move in feat/canvas-wide-search.

Bug fixes folded into this branch

  • fix(layouts): restore canvas panel after loadcloseAllPanels wipes every panel including the host canvas panel that owns the dock center zone; load flow didn't recreate it, so the center came back empty. Call ensureCenterCanvas(wsId) right after the reset and use the fresh canvas store for regions/zoomToFit.
  • fix(layouts): register new canvas store before adding restored nodes — the React CanvasPanel mounts async, so its store/ops registered after our sync createTerminal/createEditor/createBrowser calls. Nodes landed nowhere and the Welcome screen showed. Fix: explicitly ensureCanvasOpsForPanel + setActiveCanvasPanelId on the newly-minted canvas before creating nodes.

Test plan

  • Cmd+K → "Saved Layouts…" opens the modal.
  • Type a name, hit Enter → layout appears in the list.
  • Double-click (or Load button) on a row restores the canvas: nodes appear in the saved positions, regions restored, zoomToFit re-frames.
  • Deleting asks for confirmation, then removes from the list.
  • Escape closes the modal.
  • Export/Import Workspace Layout commands are gone from the palette.
  • Palette visually matches the Cmd+Shift+F overlay.
  • "Toggle File Explorer" shows ⌘⇧X in the palette row.

Known scope limits

  • Loaded layouts create fresh empty terminals — they don't restore running PTYs or scrollback (that's what the session-autosave is for).
  • Dock-zone panels (file explorer, git) aren't part of the snapshot — only canvas nodes + regions.
  • No tags / rename yet. Flat alphabetical list.

Depends on

🤖 Generated with Claude Code

Paul Horn added 5 commits April 20, 2026 15:40
Replace the window.prompt/alert-based save/load commands with a real
modal. Lists existing layouts, lets the user save the current canvas
(with regions, zoom and viewport), load, and delete — each with
proper input validation, error states, and a keyboard-friendly flow.

Reuses the existing main-process `layoutSave/layoutList/layoutLoad/
layoutDelete` IPC surface — no backend changes needed. Collapses the
two palette entries ("Save Layout As...", "Load Layout...") into a
single "Saved Layouts…" command that opens the manager.
…lay look

Three related cleanups on the command palette:

- Remove "Export Workspace Layout" and "Import Workspace Layout". The
  export command opened a native macOS save dialog and wrote a .json
  outside the app; the import command prompted via window.prompt for a
  path. Saving layouts now always goes through the in-app Saved
  Layouts manager (electron-store, named entries, modal UI), which is
  where the user expected to land when they hit "save layout".
- Restyle the palette to match the Cmd+Shift+F search overlay:
  rounded-3xl with a brighter white/20 outline, backdrop-blur, wider
  (640px), input row with a leading magnifying-glass icon, bolder row
  text, type-tinted circular icon tiles, and rows inset from the
  container with a rounded selection highlight. The two overlays now
  feel like the same surface.
- Fix the shortcut hint for Toggle File Explorer: was advertising
  ⌘⇧F, but that binding moved to Cmd+Shift+X in fix/shortcuts so
  globalSearch could take it.

Also drops the Upload/Download icon aliases made unused by the export/
import removal.
… palette

Saved Layouts modal was still wearing the old "dialog" chrome — title
bar with close icon, nested input box with a separate Save button
card, full-width borders. Promote it to the same look as the search
overlay and command palette so the three surfaces feel like one
family:

- Outer container: rounded-3xl, white/20 outline, backdrop-blur,
  offset from top with pt-40 (not centered).
- Input row: integrated into the container with a leading FloppyDisk
  icon; Save becomes a pill button on the right of the same row
  instead of a separate bordered box.
- List rows: inset from the edges with a rounded selection highlight,
  circular violet type-tile on the left, bolder primary text.
- Dropped the explicit title + X close button; Escape now closes the
  overlay (matches every other overlay in the app).
…gions

closeAllPanels wipes every panel in the workspace, including the host
'canvas' panel that owns the dock center zone. The load flow wasn't
recreating it, so the dock center came back empty — the user saw the
workspace chrome but no canvas to land nodes on.

Call ensureCenterCanvas() right after the reset so a fresh canvas host
panel exists before node creation starts. Also grab the new canvas
store via getWorkspaceCanvasStore(wsId) before calling addRegion/
zoomToFit — the useCanvasStoreApi reference captured at dialog mount
pointed at the store we just disposed.
After closeAllPanels + ensureCenterCanvas the new host 'canvas' panel
exists in dock state, but its store / ops only register when the React
CanvasPanel mounts on the next tick. The subsequent sync calls to
createTerminal / createEditor / createBrowser resolved via
getActiveCanvasOps(), which at that instant still pointed at the
disposed old canvas (or nothing), so nodes never made it onto the new
canvas — the Welcome screen rendered instead because the new canvas
had zero nodes.

Find the newly-minted canvas panel id, call ensureCanvasOpsForPanel to
build its store synchronously, then setActiveCanvasPanelId so
placePanel resolves correctly for every node we're about to create.
@PaulHorn PaulHorn force-pushed the feat/saved-layouts-manager branch from 0ec91d0 to 58a0709 Compare April 20, 2026 21:39
@PaulHorn PaulHorn merged commit ed2cbad into main Apr 20, 2026
3 checks passed
@PaulHorn PaulHorn deleted the feat/saved-layouts-manager branch April 20, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant