Skip to content

Split view: two documents side by side in one window #28

Description

@criptogus

Summary

Add split view — open two documents side by side in the same window. This is the "compare" primitive (Word's View side by side): review a contract against its previous version, a proposal against its template, a deck against the brief.

Motivation

  • Document work is inherently comparative; today the only options are switching tabs (loses context) or opening a second window.
  • The tab system already keeps every tab as its own WebContentsView (apps/shell/src/main/tab-manager.ts) — only the active one is visible. Split view is a layout change on top of that model: two views visible with a draggable divider. No engine work, no new document model.
  • Familiar pattern for office users (Word, Google Docs both have side-by-side) → does not hurt intuitiveness; it reduces context-switch friction.

Proposed UX

  • Drag a tab onto the edge of the editor area → splits horizontally or vertically (drop indicator shows which).
  • Alternatively: right-click tab → "Split left / Split right / Split above / Split below".
  • Divider draggable; double-click resets to 50/50. Active split highlighted in the tab bar; each split shows its own scroll/zoom state.
  • Close a split by dragging its tab back to the tab bar or via the tab's close button (closes the pane, not the file).
  • Keyboard: Cmd/Ctrl+\ toggles split of the current tab; Cmd/Ctrl+1/2 focuses first/second pane (proposal).
  • State is per-window and not persisted across restarts (v1) — keep it simple.

Implementation notes

  • Layout model: extend apps/shell/src/main/tab-manager.ts (or add a layout-manager.ts) from "one active visible view" to "a split tree" — minimal viable v1: a single split (2 panes), each pane holding one TabRecord. Reuse existing setBounds/resize logic (contentBounds(), trackHtmlFullScreen).
  • Renderer: apps/shell/src/renderer/src/TabBar.tsx needs drop-target affordances; AppFrame.tsx renders the split state (which tabs are visible + divider position).
  • IPC: extend TABS_CHANNELS (tabs:split, tabs:unsplit, tabs:set-divider, focus events) in apps/shell/src/shared/tabs-api.ts + preload.
  • The AI panel: with a split, the panel should attach to the focused pane (session continuity per document already works via chatId — verify the panel doesn't assume a single active doc).
  • Do not touch the apps (apps/{docs,sheets,slides,pdf}) unless the AI-panel focus issue forces a small, well-scoped change.

Acceptance criteria

  • Any two tabs can be shown side by side (drag + context-menu paths both work).
  • Both panes are independently scrollable/zoomable; divider drag resizes both smoothly.
  • Closing/unsplitting returns to single-tab layout without losing either file.
  • AI panel follows the focused pane (its session id stays per-document).
  • No regression in single-tab behavior (tab switching, fullscreen slideshow covers the whole window).

Out of scope

  • More than 2 panes, persisted layouts, split-scrolling sync (scroll one, mirrors other), side-by-side inside a single document (diff view) — those are follow-ups.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions