Skip to content

refactor(workspace): split workspace.tsx into panels and hooks#131

Merged
liam-russell merged 3 commits into
mainfrom
refactor/split-workspace-tsx
Jul 6, 2026
Merged

refactor(workspace): split workspace.tsx into panels and hooks#131
liam-russell merged 3 commits into
mainfrom
refactor/split-workspace-tsx

Conversation

@liam-russell

Copy link
Copy Markdown
Contributor

Type

  • refactor — internal change, no behavior change

Summary

  • No user-visible change. Internal-only: split the 1,728-line workspace.tsx into focused panel components (WorkspaceHeader, GraphTabPanel, TerminalTabPanel, WorkspaceDialogs) and data-fetching/subscription hooks under app/src/renderer/hooks/ (terminal session management, worktree selection, commit diff state, file watchers, UI persistence, etc.), leaving workspace.tsx as a ~600-line composition root.
  • Also fixed the two pre-existing no-unstable-nested-components lint warnings in WorktreeSidebar.tsx by hoisting its inline context-menu builders (used by the row right-click menu and the "…" quick-actions menu) to module-level functions that take their dependencies as parameters.

Why

workspace.tsx was ~3x the next-largest renderer file and the highest-friction file in the repo — most feature work lands there. Splitting it into panels/hooks unblocks other renderer work (#117).

Screenshots / recordings

N/A — pure refactor, no visual or behavioral change.

Breaking changes

None.

Test plan

  • pnpm lint, pnpm typecheck, pnpm test all pass.
  • pnpm --filter app build && pnpm test:e2e — full E2E suite passes (14 spec files, all green), including daily-workflow, worktree-workflow, commit-workflow, file-editor-workflow, agent-workflow, and sidebar-collapse — the specs most likely to catch a regression from this move.
  • Manually booted pnpm dev and confirmed the app launches cleanly with no renderer console errors.
  • No exported function/type names changed, and no external imports of workspace.tsx internals existed, so no other files needed updates beyond the two touched here.

Closes #117

workspace.tsx had grown to ~1,728 lines and was the highest-friction file
in the repo. Extract panel-switching JSX (header, graph, terminal, dialog
wiring) into app/src/renderer/workspace/*.tsx, and data-fetching/watcher/
terminal-session logic into new hooks under app/src/renderer/hooks/,
leaving workspace.tsx as a ~600-line composition root.

Also fixes the two no-unstable-nested-components lint warnings in
WorktreeSidebar.tsx by hoisting its inline context-menu builders to
module-level functions.

Pure refactor, no behavior change — verified via full E2E suite plus a
manual pnpm dev boot.

Closes #117
Copilot AI review requested due to automatic review settings July 6, 2026 09:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the renderer workspace route by decomposing the previously very large workspace.tsx into focused panel components and reusable hooks, aiming to reduce coupling and make workspace feature development easier while preserving existing behavior.

Changes:

  • Extracted top-level UI sections into dedicated panels/components (header, graph tab, terminal tab, dialogs).
  • Moved stateful workspace behaviors (worktree selection, terminals, watchers, UI persistence, recent workspaces, etc.) into hooks under app/src/renderer/hooks/.
  • Refactored WorktreeSidebar context/quick-action menus to module-level builders to address unstable nested component lint warnings.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/src/renderer/routes/workspace.tsx Turns workspace.tsx into a composition root by wiring extracted panels + hooks.
app/src/renderer/workspace/WorktreeSidebar.tsx Hoists menu-building logic to module scope and applies formatting/refactor cleanup.
app/src/renderer/workspace/WorkspaceHeader.tsx New header component encapsulating titlebar chrome + workspace switcher.
app/src/renderer/workspace/GraphTabPanel.tsx New graph tab wrapper that owns graph + diff panel wiring.
app/src/renderer/workspace/TerminalTabPanel.tsx New terminal tab wrapper for session tabs, shell picker, and panes.
app/src/renderer/workspace/WorkspaceDialogs.tsx New component bundling workspace modal dialogs into one place.
app/src/renderer/hooks/useWorktreeSelection.ts New hook encapsulating initial selection + switch/delete/create-hook flows.
app/src/renderer/hooks/useTerminalManager.tsx New hook encapsulating terminal lifecycle, buffers, and context menu actions.
app/src/renderer/hooks/useWorkspaceFileWatchers.ts New hook consolidating watchers/subscriptions and workspace-switch cleanup.
app/src/renderer/hooks/useWorkspaceUiPersistence.ts New hook for sessionStorage mirroring and sidebar shortcut wiring.
app/src/renderer/hooks/useRemoteOps.ts New hook for fetch/pull/push actions and in-flight state mirroring.
app/src/renderer/hooks/useRecentWorkspaces.ts New hook for recent workspace list loading + navigation switching.
app/src/renderer/hooks/useCommitDiffState.ts New hook for commit/range diff selection state used by the graph tab.
app/src/renderer/hooks/useScaffoldKickoff.ts New hook for “new from idea” scaffold kickoff behavior.
app/src/renderer/hooks/useAgentConfig.ts New hook for loading the AI agent configuration.
app/src/renderer/hooks/useAvailableShells.ts New hook for loading shells used by the terminal shell picker.
app/src/renderer/hooks/useAutoUpdateListeners.ts New hook wiring updater IPC events into the update store.
app/src/renderer/hooks/useEditorTabsForWorktree.ts New hook deriving editor tabs scoped to the active worktree.
app/src/renderer/hooks/useFileEditorActions.ts New hook for open/save/reload editor tab operations.

Comment thread app/src/renderer/workspace/WorktreeSidebar.tsx Outdated
Comment thread app/src/renderer/workspace/WorktreeSidebar.tsx Outdated
Comment thread app/src/renderer/hooks/useWorkspaceUiPersistence.ts Outdated
Comment thread app/src/renderer/workspace/WorkspaceHeader.tsx
- WorktreeSidebar: reuse the shared toast-context ToastFn type instead of
  a local duplicate that could drift from ToastData['variant'].
- Export TerminalLayout from workspace-store and use it instead of a bare
  string in useWorkspaceUiPersistence and TerminalTabPanel.
- WorkspaceHeader: drop the recentWorkspaces prop — it was never read
  (the switcher always reloads fresh via loadRecentWorkspaces), matching
  behavior already present before the split.
# Conflicts:
#	app/src/renderer/routes/workspace.tsx
#	app/src/renderer/workspace/WorktreeSidebar.tsx
@liam-russell liam-russell merged commit d99e15d into main Jul 6, 2026
15 checks passed
@liam-russell liam-russell deleted the refactor/split-workspace-tsx branch July 6, 2026 10:19
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.

Split workspace.tsx (1,578 lines) into panels and hooks

2 participants