Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
111 lines
4.1 KiB
TypeScript
111 lines
4.1 KiB
TypeScript
/**
|
||
* `Workspace` — the IDE shell rendered when at least one project tab is open
|
||
* (or when the launcher overlay is forced visible).
|
||
*
|
||
* Layout (full remaining height):
|
||
*
|
||
* ┌──────────────────────────────────────────────────────────┐
|
||
* │ PROJECT TABS [ alpha × ][ beta × ] [+] │
|
||
* ├────────────────┬─────────────────────────────────────────┤
|
||
* │ SIDEBAR ≈320px │ MAIN — LayoutGrid (fills remaining) │
|
||
* │ [Agents][Tmp.] │ │
|
||
* │ [Git] │ │
|
||
* │ panel content │ │
|
||
* └────────────────┴─────────────────────────────────────────┘
|
||
*
|
||
* The sidebar panel is selected via `sidebarTab`; the LayoutGrid fills the rest.
|
||
* All content is passed as render props / children; no domain logic here.
|
||
*/
|
||
|
||
import { cn } from "@/shared";
|
||
|
||
export type SidebarTab = "agents" | "templates" | "git";
|
||
|
||
interface WorkspaceProps {
|
||
/** Project tab bar (optional — hidden when no projects are open). */
|
||
projectTabBar?: React.ReactNode;
|
||
/** Whether to show the launcher overlay instead of the sidebar+main layout. */
|
||
showLauncher?: boolean;
|
||
/** The launcher component (shown when showLauncher is true). */
|
||
launcher?: React.ReactNode;
|
||
/** Currently-selected sidebar tab. */
|
||
sidebarTab: SidebarTab;
|
||
onSidebarTab: (tab: SidebarTab) => void;
|
||
/** Panel content for the sidebar body. */
|
||
agentsPanel: React.ReactNode;
|
||
templatesPanel: React.ReactNode;
|
||
gitPanel: React.ReactNode;
|
||
/** The main LayoutGrid area. */
|
||
layoutGrid: React.ReactNode;
|
||
}
|
||
|
||
const SIDEBAR_TABS: { id: SidebarTab; label: string }[] = [
|
||
{ id: "agents", label: "Agents" },
|
||
{ id: "templates", label: "Templates" },
|
||
{ id: "git", label: "Git" },
|
||
];
|
||
|
||
export function Workspace({
|
||
projectTabBar,
|
||
showLauncher = false,
|
||
launcher,
|
||
sidebarTab,
|
||
onSidebarTab,
|
||
agentsPanel,
|
||
templatesPanel,
|
||
gitPanel,
|
||
layoutGrid,
|
||
}: WorkspaceProps) {
|
||
return (
|
||
<div className="flex flex-1 flex-col overflow-hidden">
|
||
{/* ── Project tab bar ── */}
|
||
{projectTabBar}
|
||
|
||
{showLauncher ? (
|
||
// No active project: show the centred launcher.
|
||
<div className="flex flex-1 flex-col overflow-auto">{launcher}</div>
|
||
) : (
|
||
// Active project: sidebar + main grid.
|
||
<div className="flex flex-1 overflow-hidden">
|
||
{/* ── Sidebar ── */}
|
||
<aside className="flex w-80 shrink-0 flex-col border-r border-border bg-surface">
|
||
{/* Sidebar tab strip */}
|
||
<div
|
||
className="flex shrink-0 border-b border-border"
|
||
>
|
||
{SIDEBAR_TABS.map((t) => (
|
||
<button
|
||
key={t.id}
|
||
type="button"
|
||
aria-selected={sidebarTab === t.id}
|
||
onClick={() => onSidebarTab(t.id)}
|
||
className={cn(
|
||
"flex-1 px-3 py-2 text-xs font-medium transition-colors",
|
||
sidebarTab === t.id
|
||
? "border-b-2 border-primary text-content"
|
||
: "text-muted hover:text-content",
|
||
)}
|
||
>
|
||
{t.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
{/* Sidebar panel body */}
|
||
<div className="flex-1 overflow-auto p-2">
|
||
{sidebarTab === "agents" && agentsPanel}
|
||
{sidebarTab === "templates" && templatesPanel}
|
||
{sidebarTab === "git" && gitPanel}
|
||
</div>
|
||
</aside>
|
||
|
||
{/* ── Main: terminal grid ── */}
|
||
<main className="flex flex-1 flex-col overflow-hidden">
|
||
{layoutGrid}
|
||
</main>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|