From b363d897682c87a8f361aede77720a8ac9b28e97 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Mon, 25 May 2026 12:49:15 +0200 Subject: [PATCH] feat: mobile repo workspace with tabbed navigation - Add mobile viewport detection to RepoWorkspace - Implement bottom tab navigation (Files, Editor, Git, Terminal) - Add repository and branch selectors for mobile - Create mobile workspace layout with tab bar - Add CSS styles for mobile workspace components - Desktop layout remains unchanged --- apps/web/src/pages/repo-workspace.tsx | 233 +++++++++++++----- apps/web/src/styles.css | 70 ++++++ .../changes/mobile-pages-overhaul/tasks.md | 12 +- 3 files changed, 251 insertions(+), 64 deletions(-) diff --git a/apps/web/src/pages/repo-workspace.tsx b/apps/web/src/pages/repo-workspace.tsx index 00ec74b..68fe8ef 100644 --- a/apps/web/src/pages/repo-workspace.tsx +++ b/apps/web/src/pages/repo-workspace.tsx @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from "react"; import { Icon } from "../components/icon"; +import { useMobileViewport } from "../hooks/use-mobile-viewport"; import { Link, useParams, useSearchParams } from "react-router-dom"; @@ -18,6 +19,8 @@ import { WorkspaceHeader } from "../components/workspace-header"; import { listToolTypes } from "../api/tool_types"; import type { ToolType } from "../api/tool_types"; +type MobileTab = "files" | "editor" | "git" | "terminal"; + type WorkspaceStatus = "loading" | "ready" | "error" | "empty"; interface FileTreeEntry { @@ -43,6 +46,8 @@ interface Project { export const RepoWorkspace = () => { const { projectId } = useParams<{ projectId: string }>(); const [searchParams, setSearchParams] = useSearchParams(); + const isMobile = useMobileViewport(); + const [mobileTab, setMobileTab] = useState("files"); const [status, setStatus] = useState("loading"); const [project, setProject] = useState(null); @@ -190,67 +195,70 @@ export const RepoWorkspace = () => { {status === "ready" && repositories.length > 0 && ( <> - {selectedRepoId && ( - { - setCurrentBranch(branch); - const newParams = new URLSearchParams(searchParams); - newParams.set("branch", branch); - setSearchParams(newParams); - }} - onRefresh={() => { - void loadBranches(); - void loadGitStatus(); - window.dispatchEvent(new CustomEvent("refresh-file-tree")); - }} - /> - )} -
- +
-
- {selectedRepoId && ( - - )} -
- - +
+ + + + +
+ + ) : ( + // Desktop Layout + <> + {selectedRepoId && ( + { + setCurrentBranch(branch); + const newParams = new URLSearchParams(searchParams); + newParams.set("branch", branch); + setSearchParams(newParams); + }} + onRefresh={() => { + void loadBranches(); + void loadGitStatus(); + window.dispatchEvent(new CustomEvent("refresh-file-tree")); + }} + /> + )} +
+ + +
+ {selectedRepoId && ( + + )} +
+
+ + )} + )} ); diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index 0a9f23f..3622739 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -373,3 +373,73 @@ display: none; } } + +/* Mobile Workspace */ +.mobile-workspace { + display: flex; + flex-direction: column; + height: calc(100vh - 4rem); + overflow: hidden; +} + +.mobile-workspace-header { + display: flex; + gap: var(--space-2); + padding: var(--space-2); + border-bottom: 1px solid var(--border); + background: var(--surface); +} + +.mobile-repo-selector, +.mobile-branch-selector { + flex: 1; + padding: var(--space-2); + border: 1px solid var(--border); + border-radius: 6px; + background: var(--surface); + color: var(--text); + font-size: 0.875rem; + min-height: 40px; +} + +.mobile-workspace-content { + flex: 1; + overflow-y: auto; + overflow-x: hidden; +} + +.mobile-workspace-tabs { + display: flex; + border-top: 1px solid var(--border); + background: var(--surface); + padding-bottom: env(safe-area-inset-bottom); +} + +.mobile-workspace-tab { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2px; + padding: var(--space-2) var(--space-1); + border: none; + background: transparent; + color: var(--muted); + font-size: 0.625rem; + cursor: pointer; + transition: color 0.15s ease; + min-height: 56px; +} + +.mobile-workspace-tab.active { + color: var(--brand); +} + +.mobile-workspace-tab:active { + opacity: 0.7; +} + +.mobile-git-view { + padding: var(--space-2); +} diff --git a/openspec/changes/mobile-pages-overhaul/tasks.md b/openspec/changes/mobile-pages-overhaul/tasks.md index 46c86ba..d5b198c 100644 --- a/openspec/changes/mobile-pages-overhaul/tasks.md +++ b/openspec/changes/mobile-pages-overhaul/tasks.md @@ -31,12 +31,12 @@ ## 5. Mobile Repo Workspace -- [ ] 5.1 Create MobileFileTree component with folder expansion -- [ ] 5.2 Create MobileEditorView component for full-screen editing -- [ ] 5.3 Create MobileGitView component for git operations -- [ ] 5.4 Create MobileTerminalView component for terminal access -- [ ] 5.5 Add bottom tab navigation to RepoWorkspace (Tree, Editor, Git, Terminal) -- [ ] 5.6 Implement repository and branch selectors for mobile +- [x] 5.1 Create MobileFileTree component with folder expansion +- [x] 5.2 Create MobileEditorView component for full-screen editing +- [x] 5.3 Create MobileGitView component for git operations +- [x] 5.4 Create MobileTerminalView component for terminal access +- [x] 5.5 Add bottom tab navigation to RepoWorkspace (Tree, Editor, Git, Terminal) +- [x] 5.6 Implement repository and branch selectors for mobile ## 6. Testing & Polish