Canvas: Fix layout, get rid of scroll bars
Change-Id: I3244784ee741e93565190e538472723ffadfb754
diff --git a/apps/canvas/front/src/App.tsx b/apps/canvas/front/src/App.tsx
index f37370a..0f59fb9 100644
--- a/apps/canvas/front/src/App.tsx
+++ b/apps/canvas/front/src/App.tsx
@@ -6,12 +6,12 @@
import { Integrations } from "./Integrations";
import { Toaster } from "./components/ui/toaster";
import { ProjectSelect } from "./ProjectSelect";
-import { Logs } from "./components/logs";
+import { Logs } from "./Logs";
export default function App() {
return (
<ReactFlowProvider>
- <div className="h-screen flex flex-col">
+ <div className="h-screen flex flex-col p-1">
<AppImpl />
<Toaster />
</div>
@@ -22,7 +22,7 @@
function AppImpl() {
return (
<Tabs defaultValue="canvas" className="flex-1 flex flex-col min-h-0">
- <div className="flex items-center justify-between px-4 border-b">
+ <div className="flex items-center justify-between border-b">
<TabsList>
<TabsTrigger value="canvas">Canvas</TabsTrigger>
<TabsTrigger value="logs">Logs</TabsTrigger>
@@ -31,16 +31,16 @@
</TabsList>
<ProjectSelect />
</div>
- <TabsContent value="canvas" className="flex-1 min-h-0">
+ <TabsContent value="canvas" className="!mt-0 flex-1 min-h-0">
<CanvasBuilder />
</TabsContent>
- <TabsContent value="config" className="flex-1 min-h-0">
+ <TabsContent value="config" className="!mt-0 flex-1 min-h-0">
<Config />
</TabsContent>
- <TabsContent value="integrations" className="flex-1 min-h-0">
+ <TabsContent value="integrations" className="!mt-0 flex-1 min-h-0">
<Integrations />
</TabsContent>
- <TabsContent value="logs" className="flex-1 min-h-0">
+ <TabsContent value="logs" className="!mt-0 flex-1 min-h-0">
<Logs />
</TabsContent>
</Tabs>
diff --git a/apps/canvas/front/src/Canvas.tsx b/apps/canvas/front/src/Canvas.tsx
index 0b22a36..c794ade 100644
--- a/apps/canvas/front/src/Canvas.tsx
+++ b/apps/canvas/front/src/Canvas.tsx
@@ -6,7 +6,7 @@
export function CanvasBuilder() {
return (
- <ResizablePanelGroup direction="horizontal" style={{ width: "100vw", height: "calc(100vh - 100px)" }}>
+ <ResizablePanelGroup direction="horizontal" className="w-full h-full">
<ResizablePanel defaultSize={80}>
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={80}>
diff --git a/apps/canvas/front/src/Config.tsx b/apps/canvas/front/src/Config.tsx
index 7a93634..2b8b1f7 100644
--- a/apps/canvas/front/src/Config.tsx
+++ b/apps/canvas/front/src/Config.tsx
@@ -2,7 +2,6 @@
import { AppNode, useEnv, useProjectId } from "./lib/state";
import { generateDodoConfig } from "./lib/config";
import { useEffect, useMemo, useState } from "react";
-import { Card, CardContent } from "./components/ui/card";
import JSONView from "@microlink/react-json-view";
export function Config() {
@@ -18,19 +17,15 @@
}, [n, setNodes]);
const config = useMemo(() => generateDodoConfig(projectId, nodes, env) || {}, [projectId, nodes, env]);
return (
- <Card className="h-full flex flex-col">
- <CardContent className="flex-1 min-h-0 p-4">
- <div className="h-full p-4 bg-muted rounded-lg overflow-auto">
- <JSONView
- src={config as object}
- theme="rjv-default"
- name={false}
- displayDataTypes={false}
- enableClipboard={true}
- style={{ fontFamily: "JetBrains Mono" }}
- />
- </div>
- </CardContent>
- </Card>
+ <div className="h-full p-4 bg-muted rounded-lg overflow-auto">
+ <JSONView
+ src={config as object}
+ theme="rjv-default"
+ name={false}
+ displayDataTypes={false}
+ enableClipboard={true}
+ style={{ fontFamily: "JetBrains Mono" }}
+ />
+ </div>
);
}
diff --git a/apps/canvas/front/src/Integrations.tsx b/apps/canvas/front/src/Integrations.tsx
index eb68a2a..436c1e8 100644
--- a/apps/canvas/front/src/Integrations.tsx
+++ b/apps/canvas/front/src/Integrations.tsx
@@ -70,7 +70,7 @@
};
return (
- <div className="px-5 space-y-6">
+ <div className="px-4 py-1 space-y-6">
<div>
<div className="flex items-center space-x-2">
<Checkbox checked={!!githubService} disabled />
diff --git a/apps/canvas/front/src/components/logs.tsx b/apps/canvas/front/src/Logs.tsx
similarity index 86%
rename from apps/canvas/front/src/components/logs.tsx
rename to apps/canvas/front/src/Logs.tsx
index a2bf1ba..97718df 100644
--- a/apps/canvas/front/src/components/logs.tsx
+++ b/apps/canvas/front/src/Logs.tsx
@@ -1,7 +1,6 @@
import { useCallback, useEffect, useState, useRef, useMemo } from "react";
import { useProjectId, useEnv } from "@/lib/state";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { useToast } from "@/hooks/use-toast";
// ANSI escape sequence regex
@@ -99,10 +98,11 @@
}, [sortedServices, selectedService]);
return (
- <Card className="h-full flex flex-col">
- <CardHeader>
+ <div className="flex flex-col h-full">
+ <div className="flex-none w-full flex flex-row justify-start items-center gap-2 px-4 py-1">
+ <div>Service</div>
<Select value={selectedService} onValueChange={setSelectedService}>
- <SelectTrigger>
+ <SelectTrigger className="w-1/4">
<SelectValue placeholder="Select a service" />
</SelectTrigger>
<SelectContent>
@@ -113,17 +113,15 @@
))}
</SelectContent>
</Select>
- </CardHeader>
- <CardContent className="flex-1 min-h-0">
- {selectedService && (
- <pre
- ref={preRef}
- className="h-full p-4 bg-muted rounded-lg overflow-auto font-['JetBrains_Mono'] whitespace-pre-wrap break-all"
- >
- {cleanAnsiEscapeSequences(logs) || "No logs available"}
- </pre>
- )}
- </CardContent>
- </Card>
+ </div>
+ {selectedService && (
+ <pre
+ ref={preRef}
+ className="flex-1 h-full p-4 bg-muted rounded-lg overflow-auto font-['JetBrains_Mono'] whitespace-pre-wrap break-all"
+ >
+ {cleanAnsiEscapeSequences(logs) || "No logs available"}
+ </pre>
+ )}
+ </div>
);
}
diff --git a/apps/canvas/front/src/ProjectSelect.tsx b/apps/canvas/front/src/ProjectSelect.tsx
index 5178b5e..a643eaa 100644
--- a/apps/canvas/front/src/ProjectSelect.tsx
+++ b/apps/canvas/front/src/ProjectSelect.tsx
@@ -6,6 +6,8 @@
import { Button } from "./components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "./components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
+import { Separator } from "./components/ui/separator";
+import { Plus } from "lucide-react";
export function ProjectSelect() {
const { toast } = useToast();
@@ -97,24 +99,28 @@
}, [name, setCreateNewOpen, toast, store, refreshProjects]);
return (
<Select onValueChange={onSelect} value={project}>
- <SelectTrigger className="w-[200px]">
+ <SelectTrigger className="w-[200px] !border-none !shadow-none !focus:ring-0 !focus:ring-offset-0">
<SelectValue placeholder="Choose Project" defaultValue={project} />
</SelectTrigger>
<SelectContent>
+ {projects.map((p) => (
+ <SelectItem key={p.id} value={p.id}>
+ {p.name}
+ </SelectItem>
+ ))}
+ <Separator />
<SelectItem value={"create-new"}>
<Dialog open={createNewOpen} onOpenChange={setCreateNewOpen}>
- <DialogTrigger>Create New</DialogTrigger>
+ <DialogTrigger className="flex flex-row items-center">
+ <Plus />
+ Create New
+ </DialogTrigger>
<DialogContent>
<Input type="text" placeholder="Name" onChange={updateName} />
<Button onClick={createNew}>Create New</Button>
</DialogContent>
</Dialog>
</SelectItem>
- {projects.map((p) => (
- <SelectItem key={p.id} value={p.id}>
- {p.name}
- </SelectItem>
- ))}
</SelectContent>
</Select>
);