diff --git a/app/[workspace]/project/[projectId]/build/page.tsx b/app/[workspace]/project/[projectId]/build/page.tsx
index 8fe36f7..1cc0b2c 100644
--- a/app/[workspace]/project/[projectId]/build/page.tsx
+++ b/app/[workspace]/project/[projectId]/build/page.tsx
@@ -211,31 +211,6 @@ function LayoutsContent({ surfaces, projectId, workspace, activeSurfaceId, onSel
// ── Shared mode tab bar ───────────────────────────────────────────────────────
-type CodeMode = "browse" | "agent" | "terminal";
-
-function ModeTabs({ mode, onChange }: { mode: CodeMode; onChange: (m: CodeMode) => void }) {
- const tabs: { id: CodeMode; label: string }[] = [
- { id: "browse", label: "Browse" },
- { id: "agent", label: "Agent" },
- { id: "terminal", label: "Terminal" },
- ];
- return (
-
- {tabs.map(t => (
- onChange(t.id)} style={{
- padding: "10px 14px", border: "none", background: "transparent", cursor: "pointer",
- fontSize: "0.76rem", fontWeight: mode === t.id ? 600 : 450,
- color: mode === t.id ? "#1a1a1a" : "#a09a90",
- borderBottom: mode === t.id ? "2px solid #1a1a1a" : "2px solid transparent",
- fontFamily: "Outfit, sans-serif", whiteSpace: "nowrap",
- }}>
- {t.label}
-
- ))}
-
- );
-}
-
// ── Agent mode ────────────────────────────────────────────────────────────────
interface AgentSession {
@@ -800,23 +775,39 @@ function AgentMode({ projectId, appName, appPath }: { projectId: string; appName
);
}
-// ── Terminal mode (Phase 4 placeholder) ───────────────────────────────────────
+// ── Terminal panel — collapsible bottom strip ─────────────────────────────────
+
+function TerminalPanel({ appName }: { appName: string }) {
+ const [open, setOpen] = useState(false);
+ const PANEL_HEIGHT = 220;
-function TerminalMode({ appName }: { appName: string }) {
return (
-
-
-
⌨
-
-
Terminal — Phase 4
-
+
+ {/* Header / toggle bar */}
+
setOpen(o => !o)}
+ style={{
+ display: "flex", alignItems: "center", gap: 8, padding: "0 14px",
+ height: 32, flexShrink: 0, width: "100%", border: "none",
+ background: "transparent", cursor: "pointer", textAlign: "left",
+ }}
+ >
+ ▲
+ Terminal
+ {appName && {appName} }
+ Phase 4
+
+
+ {/* Body */}
+ {open && (
+
+
{appName
- ? `A live shell into the ${appName} container via xterm.js + Theia PTY. Coming in Phase 4.`
- : "Select an app first, then open a live shell into its container."}
+ ? `Live shell into the ${appName} container via xterm.js + Theia PTY — coming in Phase 4.`
+ : "Select an app from the left, then open a live shell into its container."}
-
Coming in Phase 4
-
+ )}
);
}
@@ -968,12 +959,6 @@ function BuildHubInner() {
const setSection = (s: string) => router.push(`/${workspace}/project/${projectId}/build?section=${s}`, { scroll: false });
- const codeMode = (searchParams.get("mode") as CodeMode | null) ?? "browse";
- const setCodeMode = (m: CodeMode) => {
- const sp = new URLSearchParams({ section: "code", ...(activeApp ? { app: activeApp, root: activeRoot } : {}), mode: m });
- router.push(`/${workspace}/project/${projectId}/build?${sp.toString()}`, { scroll: false });
- };
-
return (
@@ -1014,14 +999,38 @@ function BuildHubInner() {
{/* ── Content ── */}
+
+ {/* Code section — persistent split: Browse (left) | Agent (right), Terminal (bottom) */}
{section === "code" && (
-
- {codeMode === "browse" &&
}
- {codeMode === "agent" &&
}
- {codeMode === "terminal" &&
}
+ {/* Main split row */}
+
+ {/* Left: Browse */}
+
+ {/* Browse header */}
+
+ Browse
+ {activeApp && {activeApp} }
+
+
+
+
+ {/* Right: Agent */}
+
+ {/* Agent header */}
+
+ Agent
+ {activeApp && {activeApp} }
+
+
+
+
+
+ {/* Bottom: Terminal (collapsible) */}
+
)}
+
{section === "layouts" && (
{ setActiveSurfaceId(id); navigate({ section: "layouts", surface: id }); }} />
)}