From ab47c45f6749a691f5540dc5247977737e309dc4 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Fri, 16 Jan 2026 12:17:27 +0100 Subject: [PATCH 01/12] Add file tree sidebar toggle --- src/App.tsx | 6 + src/features/app/components/MainHeader.tsx | 24 +- .../files/components/FileTreePanel.tsx | 218 ++++++++++++++++++ src/features/layout/hooks/useLayoutNodes.tsx | 67 +++--- src/styles/file-tree.css | 81 +++++++ 5 files changed, 367 insertions(+), 29 deletions(-) create mode 100644 src/features/files/components/FileTreePanel.tsx create mode 100644 src/styles/file-tree.css diff --git a/src/App.tsx b/src/App.tsx index d851019d0..4087e1c0b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ import "./styles/update-toasts.css"; import "./styles/composer.css"; import "./styles/diff.css"; import "./styles/diff-viewer.css"; +import "./styles/file-tree.css"; import "./styles/debug.css"; import "./styles/terminal.css"; import "./styles/plan.css"; @@ -115,6 +116,7 @@ function MainApp() { const [gitPanelMode, setGitPanelMode] = useState<"diff" | "log" | "issues">( "diff" ); + const [filePanelMode, setFilePanelMode] = useState<"git" | "files">("git"); const [accessMode, setAccessMode] = useState("current"); const [activeTab, setActiveTab] = useState< "projects" | "codex" | "git" | "log" @@ -753,6 +755,10 @@ function MainApp() { onCopyThread: handleCopyThread, onToggleTerminal: handleToggleTerminal, showTerminalButton: !isCompact, + filePanelMode, + onToggleFilePanel: () => { + setFilePanelMode((prev) => (prev === "git" ? "files" : "git")); + }, centerMode, onExitDiff: () => { setCenterMode("chat"); diff --git a/src/features/app/components/MainHeader.tsx b/src/features/app/components/MainHeader.tsx index 924733d60..5b1e9fff8 100644 --- a/src/features/app/components/MainHeader.tsx +++ b/src/features/app/components/MainHeader.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { Check, Copy, Terminal } from "lucide-react"; +import { Check, Copy, Folder, GitBranch, Terminal } from "lucide-react"; import { revealItemInDir } from "@tauri-apps/plugin-opener"; import type { BranchInfo, WorkspaceInfo } from "../../../types"; @@ -19,6 +19,8 @@ type MainHeaderProps = { onToggleTerminal: () => void; isTerminalOpen: boolean; showTerminalButton?: boolean; + filePanelMode: "git" | "files"; + onToggleFilePanel: () => void; }; export function MainHeader({ @@ -37,6 +39,8 @@ export function MainHeader({ onToggleTerminal, isTerminalOpen, showTerminalButton = true, + filePanelMode, + onToggleFilePanel, }: MainHeaderProps) { const [menuOpen, setMenuOpen] = useState(false); const [infoOpen, setInfoOpen] = useState(false); @@ -282,6 +286,24 @@ export function MainHeader({
+ {showTerminalButton && ( + {isFolder && isExpanded && node.children.length > 0 && ( +
+ {node.children.map((child) => renderNode(child, depth + 1))} +
+ )} +
+ ); + }; + + return ( + + ); +} diff --git a/src/features/layout/hooks/useLayoutNodes.tsx b/src/features/layout/hooks/useLayoutNodes.tsx index 0371f9b48..706dcf15f 100644 --- a/src/features/layout/hooks/useLayoutNodes.tsx +++ b/src/features/layout/hooks/useLayoutNodes.tsx @@ -9,6 +9,7 @@ import { UpdateToast } from "../../update/components/UpdateToast"; import { Composer } from "../../composer/components/Composer"; import { GitDiffPanel } from "../../git/components/GitDiffPanel"; import { GitDiffViewer } from "../../git/components/GitDiffViewer"; +import { FileTreePanel } from "../../files/components/FileTreePanel"; import { DebugPanel } from "../../debug/components/DebugPanel"; import { PlanPanel } from "../../plan/components/PlanPanel"; import { TabBar } from "../../app/components/TabBar"; @@ -108,6 +109,8 @@ type LayoutNodesOptions = { onCopyThread: () => void | Promise; onToggleTerminal: () => void; showTerminalButton: boolean; + filePanelMode: "git" | "files"; + onToggleFilePanel: () => void; centerMode: "chat" | "diff"; onExitDiff: () => void; activeTab: "projects" | "codex" | "git" | "log"; @@ -348,6 +351,8 @@ export function useLayoutNodes(options: LayoutNodesOptions): LayoutNodesResult { onToggleTerminal={options.onToggleTerminal} isTerminalOpen={options.terminalOpen} showTerminalButton={options.showTerminalButton} + filePanelMode={options.filePanelMode} + onToggleFilePanel={options.onToggleFilePanel} /> ) : null; @@ -374,34 +379,40 @@ export function useLayoutNodes(options: LayoutNodesOptions): LayoutNodesResult { ); - const gitDiffPanelNode = ( - - ); + const gitDiffPanelNode = + options.filePanelMode === "files" && options.activeWorkspace ? ( + + ) : ( + + ); const gitDiffViewerNode = ( Date: Fri, 16 Jan 2026 13:33:11 +0100 Subject: [PATCH 02/12] Add panel switch button and file type icons to side panels Introduces a switch button in both the file tree and git diff panels for toggling between them, improving navigation. FileTreePanel now displays file-type-specific icons. Updates related props, removes the old toggle from MainHeader, and adjusts styles for the new button. Also increases the minimum right panel width for better layout. --- package.json | 6 +- src/features/app/components/MainHeader.tsx | 24 +---- .../files/components/FileTreePanel.tsx | 101 +++++++++++++++++- src/features/git/components/GitDiffPanel.tsx | 15 ++- src/features/layout/hooks/useLayoutNodes.tsx | 6 +- .../layout/hooks/useResizablePanels.ts | 2 +- src/styles/diff.css | 31 ++++++ src/styles/sidebar.css | 1 + 8 files changed, 147 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 35ae3f765..ea373bbe9 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,14 @@ "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-process": "^2.3.1", "@tauri-apps/plugin-updater": "^2.9.0", + "@xterm/addon-fit": "^0.10.0", + "@xterm/xterm": "^5.5.0", "lucide-react": "^0.562.0", "prismjs": "^1.30.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-markdown": "^10.1.0", - "remark-gfm": "^4.0.1", - "@xterm/xterm": "^5.5.0", - "@xterm/addon-fit": "^0.10.0" + "remark-gfm": "^4.0.1" }, "devDependencies": { "@tauri-apps/cli": "^2", diff --git a/src/features/app/components/MainHeader.tsx b/src/features/app/components/MainHeader.tsx index 5b1e9fff8..924733d60 100644 --- a/src/features/app/components/MainHeader.tsx +++ b/src/features/app/components/MainHeader.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { Check, Copy, Folder, GitBranch, Terminal } from "lucide-react"; +import { Check, Copy, Terminal } from "lucide-react"; import { revealItemInDir } from "@tauri-apps/plugin-opener"; import type { BranchInfo, WorkspaceInfo } from "../../../types"; @@ -19,8 +19,6 @@ type MainHeaderProps = { onToggleTerminal: () => void; isTerminalOpen: boolean; showTerminalButton?: boolean; - filePanelMode: "git" | "files"; - onToggleFilePanel: () => void; }; export function MainHeader({ @@ -39,8 +37,6 @@ export function MainHeader({ onToggleTerminal, isTerminalOpen, showTerminalButton = true, - filePanelMode, - onToggleFilePanel, }: MainHeaderProps) { const [menuOpen, setMenuOpen] = useState(false); const [infoOpen, setInfoOpen] = useState(false); @@ -286,24 +282,6 @@ export function MainHeader({
- {showTerminalButton && ( @@ -198,10 +282,17 @@ export function FileTreePanel({ workspacePath, files }: FileTreePanelProps) { return ( diff --git a/src/styles/composer.css b/src/styles/composer.css index fbc988117..bc58f211a 100644 --- a/src/styles/composer.css +++ b/src/styles/composer.css @@ -3,7 +3,7 @@ flex-direction: column; gap: 8px; -webkit-app-region: no-drag; - padding: 12px 32px 24px; + padding: 12px var(--main-panel-padding) 24px; border-top: 1px solid var(--border-subtle); background: var(--surface-composer); grid-column: 1;