From aa108ac029e740bddbc6aa9505e288b47c4aed2d Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 10 Oct 2025 12:28:03 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A4=96=20Add=20title=20bar=20to=20lef?= =?UTF-8?q?t=20sidebar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created LeftSidebar component that wraps: - TitleBar component showing version and build date - ProjectSidebar component (refactored to remove container styling) The title bar displays 'cmux ' at the top of the left sidebar. Ctrl+P collapse/expand now applies to the entire LeftSidebar including the title bar. Changes: - New TitleBar component with tight vertical padding - New LeftSidebar wrapper component - ProjectSidebar refactored to use SidebarContent instead of SidebarContainer - App.tsx updated to use LeftSidebar instead of ProjectSidebar directly _Generated with `cmux`_ --- src/App.tsx | 4 +-- src/components/LeftSidebar.tsx | 52 +++++++++++++++++++++++++++++++ src/components/ProjectSidebar.tsx | 15 +++------ src/components/TitleBar.tsx | 39 +++++++++++++++++++++++ 4 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 src/components/LeftSidebar.tsx create mode 100644 src/components/TitleBar.tsx diff --git a/src/App.tsx b/src/App.tsx index b4cc67a218..910cab8a10 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,7 @@ import { GlobalFonts } from "./styles/fonts"; import { GlobalScrollbars } from "./styles/scrollbars"; import type { ProjectConfig } from "./config"; import type { WorkspaceSelection } from "./components/ProjectSidebar"; -import ProjectSidebar from "./components/ProjectSidebar"; +import { LeftSidebar } from "./components/LeftSidebar"; import NewWorkspaceModal from "./components/NewWorkspaceModal"; import { AIView } from "./components/AIView"; import { ErrorBoundary } from "./components/ErrorBoundary"; @@ -485,7 +485,7 @@ function AppInner() { - ` + width: ${(props) => (props.collapsed ? "32px" : "280px")}; + height: 100vh; + background: #252526; + border-right: 1px solid #1e1e1e; + display: flex; + flex-direction: column; + flex-shrink: 0; + transition: width 0.2s ease; + overflow: hidden; +`; + +interface LeftSidebarProps { + projects: Map; + workspaceMetadata: Map; + selectedWorkspace: WorkspaceSelection | null; + onSelectWorkspace: (selection: WorkspaceSelection) => void; + onAddProject: () => void; + onAddWorkspace: (projectPath: string) => void; + onRemoveProject: (path: string) => void; + onRemoveWorkspace: (workspaceId: string) => Promise<{ success: boolean; error?: string }>; + onRenameWorkspace: ( + workspaceId: string, + newName: string + ) => Promise<{ success: boolean; error?: string }>; + getWorkspaceState: (workspaceId: string) => WorkspaceState; + collapsed: boolean; + onToggleCollapsed: () => void; + onGetSecrets: (projectPath: string) => Promise; + onUpdateSecrets: (projectPath: string, secrets: Secret[]) => Promise; +} + +export function LeftSidebar(props: LeftSidebarProps) { + const { collapsed, ...projectSidebarProps } = props; + + return ( + + {!collapsed && } + + + ); +} diff --git a/src/components/ProjectSidebar.tsx b/src/components/ProjectSidebar.tsx index 8a15e5bd09..e233746a18 100644 --- a/src/components/ProjectSidebar.tsx +++ b/src/components/ProjectSidebar.tsx @@ -17,17 +17,12 @@ import SecretsModal from "./SecretsModal"; import type { Secret } from "@/types/secrets"; // Styled Components -const SidebarContainer = styled.div<{ collapsed?: boolean }>` - width: ${(props) => (props.collapsed ? "32px" : "280px")}; - height: 100vh; - background: #252526; - border-right: 1px solid #1e1e1e; +const SidebarContent = styled.div` display: flex; flex-direction: column; - flex-shrink: 0; - font-family: var(--font-primary); - transition: width 0.2s ease; + flex: 1; overflow: hidden; + font-family: var(--font-primary); `; const SidebarHeader = styled.div` @@ -563,7 +558,7 @@ const ProjectSidebar: React.FC = ({ }, [selectedWorkspace, onAddWorkspace]); return ( - + {!collapsed && ( <> @@ -794,7 +789,7 @@ const ProjectSidebar: React.FC = ({ , document.body )} - + ); }; diff --git a/src/components/TitleBar.tsx b/src/components/TitleBar.tsx new file mode 100644 index 0000000000..c168a45039 --- /dev/null +++ b/src/components/TitleBar.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import styled from "@emotion/styled"; +import { VERSION } from "@/version"; + +const TitleBarContainer = styled.div` + padding: 8px 16px; + background: #1e1e1e; + border-bottom: 1px solid #3c3c3c; + display: flex; + align-items: center; + justify-content: space-between; + font-family: var(--font-primary); + font-size: 11px; + color: #858585; + user-select: none; + flex-shrink: 0; +`; + +const TitleText = styled.div` + font-weight: 600; + letter-spacing: 0.5px; +`; + +const BuildInfo = styled.div` + font-size: 10px; + opacity: 0.7; +`; + +export function TitleBar() { + // Format build date as YYYY-MM-DD + const buildDate = VERSION.buildTime.split("T")[0]; + + return ( + + cmux {VERSION.git} + {buildDate} + + ); +} From cec0856314dda06086b6d52a33830bfacf91c7f1 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 10 Oct 2025 13:20:00 -0500 Subject: [PATCH 2/3] Improve title bar formatting and version info - Changed VERSION.git to VERSION.git_commit and VERSION.git_describe for clarity - Format date in US format (MM/DD/YYYY) instead of ISO - Add tooltip showing extended timestamp on hover over date - Remove bold from git version text - Updated version generation script to include both git commit hash and describe output The tooltip shows 'Built at ' when hovering over the build date for more detailed information. --- scripts/generate-version.sh | 8 +++++--- src/components/TitleBar.tsx | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/scripts/generate-version.sh b/scripts/generate-version.sh index 954594b927..ee43894642 100755 --- a/scripts/generate-version.sh +++ b/scripts/generate-version.sh @@ -1,7 +1,8 @@ #!/bin/bash # Generate version.ts with git information -VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "unknown") +GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") +GIT_DESCRIBE=$(git describe --tags --always --dirty 2>/dev/null || echo "unknown") TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") cat >src/version.ts <src/version.ts < - cmux {VERSION.git} - {buildDate} + cmux {VERSION.git_describe} + + {buildDate} + Built at {extendedTimestamp} + ); } From 3b74167be5092d1b9892428915b868c5700865d1 Mon Sep 17 00:00:00 2001 From: Ammar Date: Fri, 10 Oct 2025 13:25:24 -0500 Subject: [PATCH 3/3] Make version.ts regenerate on every build Changed src/version.ts to always regenerate by making it depend on a .PHONY 'version' target. This ensures the git version and timestamp are always up-to-date when running 'make dev' or 'make build'. Previously, version.ts would only be generated if it didn't exist. --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 817d106fae..b2e1d7f315 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ # Add `## Description` after the target to make it appear in `make help` .PHONY: all build dev start clean help -.PHONY: build-renderer +.PHONY: build-renderer version .PHONY: lint lint-fix fmt fmt-check fmt-shell fmt-nix fmt-nix-check fmt-shell-check typecheck static-check .PHONY: test test-unit test-integration test-watch test-coverage test-e2e .PHONY: dist dist-mac dist-win dist-linux @@ -81,9 +81,12 @@ build-renderer: ensure-deps src/version.ts ## Build renderer process @echo "Building renderer..." @bun x vite build -src/version.ts: ## Generate version file +# Always regenerate version file (marked as .PHONY above) +version: ## Generate version file @./scripts/generate-version.sh +src/version.ts: version + ## Quality checks (can run in parallel) static-check: lint typecheck fmt-check ## Run all static checks