Skip to content

Commit 1202a73

Browse files
committed
refactor: replace promo banner with global navbar and optimize workflow dashboard layout
1 parent 7720d04 commit 1202a73

9 files changed

Lines changed: 138 additions & 1150 deletions

File tree

‎app/app/flow/page.tsx‎

Lines changed: 68 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
Upload,
1414
Workflow as WorkflowIcon,
1515
} from "lucide-react";
16-
import Image from "next/image";
1716
import { useRouter } from "next/navigation";
1817
import { useCallback, useEffect, useState } from "react";
1918
import { Button } from "@/components/ui/button";
@@ -199,16 +198,17 @@ export default function FlowPage() {
199198
return (
200199
<div className="flex-1 p-11 px-14 bg-background">
201200
{/* Header */}
202-
<div className="flex items-start justify-between mb-2">
203-
<div>
204-
<h1 className="text-[30px] font-semibold text-[#1F1F23] leading-none tracking-tight">
205-
Flow
206-
</h1>
207-
<p className="text-[16px] font-normal text-[#858589] mt-2">
208-
Build workflows or run models directly
209-
</p>
210-
</div>
201+
<div className="flex items-center justify-end mb-2">
211202
<div className="flex items-center gap-2.5">
203+
<div className="relative">
204+
<Search className="absolute left-3.5 top-1/2 -translate-y-1/2 size-[18px] text-[#858589]" />
205+
<Input
206+
placeholder="Search workflows..."
207+
value={searchQuery}
208+
onChange={(e) => setSearchQuery(e.target.value)}
209+
className="pl-10.5 h-10 w-[280px] text-[15px] bg-[#EFEFEF] border-transparent rounded-[8px] placeholder-[#858589] font-normal focus-visible:ring-0 focus-visible:border-gray-300"
210+
/>
211+
</div>
212212
<Button
213213
variant="outline"
214214
onClick={importWorkflow}
@@ -227,55 +227,11 @@ export default function FlowPage() {
227227
</div>
228228
</div>
229229

230-
{/* System Workflows */}
230+
{/* Your Workflows */}
231231
<section className="mt-11">
232-
<h2 className="text-[20px] font-semibold text-gray-900 mb-1 tracking-tight">
233-
System Workflows
232+
<h2 className="text-[20px] font-semibold text-gray-900 tracking-tight mb-1">
233+
Your Workflows
234234
</h2>
235-
<p className="text-[15px] text-[#858589] mb-5">
236-
Prebuilt workflow templates - click to open and start using.
237-
</p>
238-
239-
<div className="flex flex-wrap gap-8 max-w-[1300px]">
240-
{/* Racing car template */}
241-
<button
242-
type="button"
243-
onClick={() => createWorkflow("racing-car")}
244-
className="group text-left bg-[#F3F3F3] rounded-[12px] overflow-hidden shadow-[0_1px_2px_rgba(0,0,0,0.06)] hover:shadow-md transition-all cursor-pointer flex flex-col w-[320px] shrink-0"
245-
>
246-
<div className="aspect-[16/11] relative overflow-hidden bg-gray-100 w-full">
247-
<Image
248-
src="/porsche-rear.png"
249-
alt="AI Racing Car Generator"
250-
fill
251-
className="object-cover group-hover:scale-105 transition-transform duration-300"
252-
/>
253-
</div>
254-
<div className="p-4 text-center w-full">
255-
<span className="text-[18px] font-medium text-gray-900">
256-
AI Racing Car Generator
257-
</span>
258-
</div>
259-
</button>
260-
</div>
261-
</section>
262-
263-
{/* Your Workflows */}
264-
<section className="mt-14">
265-
<div className="flex items-center justify-between mb-1">
266-
<h2 className="text-[20px] font-semibold text-gray-900 tracking-tight">
267-
Your Workflows
268-
</h2>
269-
<div className="relative">
270-
<Search className="absolute left-3.5 top-1/2 -translate-y-1/2 size-[18px] text-[#858589]" />
271-
<Input
272-
placeholder="Search workflows..."
273-
value={searchQuery}
274-
onChange={(e) => setSearchQuery(e.target.value)}
275-
className="pl-10.5 h-11 w-[360px] text-[15px] bg-[#EFEFEF] border-transparent rounded-[12px] placeholder-[#858589] font-normal focus-visible:ring-0 focus-visible:border-gray-300"
276-
/>
277-
</div>
278-
</div>
279235
<p className="text-[15px] text-[#858589] mb-5">
280236
Open one to edit, run, and review history.
281237
</p>
@@ -304,26 +260,62 @@ export default function FlowPage() {
304260
No workflows match &quot;{searchQuery}&quot;
305261
</p>
306262
) : (
307-
<div className="flex flex-wrap gap-7 max-w-[1300px]">
263+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
308264
{filtered.map((wf) => (
309265
<div
310266
key={wf.id}
311-
className="group flex flex-col bg-[#F3F3F3] rounded-[12px] overflow-hidden shadow-[0_1px_2px_rgba(0,0,0,0.06)] transition-all w-[320px] shrink-0 relative"
267+
className="group flex flex-col bg-[#F3F3F3] rounded-[12px] overflow-hidden shadow-[0_1px_2px_rgba(0,0,0,0.06)] hover:shadow-md transition-all relative cursor-pointer"
268+
onClick={() => router.push(`/app/workflows/${wf.id}`)}
269+
onKeyDown={(e) => {
270+
if (e.key === "Enter") router.push(`/app/workflows/${wf.id}`);
271+
}}
312272
>
313-
{/* Card image container */}
314-
<div className="relative aspect-[16/11] overflow-hidden w-full">
315-
<Image
316-
src="/porsche-rear.png"
317-
alt={wf.name}
318-
fill
319-
className="object-cover cursor-pointer group-hover:scale-105 transition-transform duration-300"
320-
onClick={() => router.push(`/app/workflows/${wf.id}`)}
321-
/>
273+
{/* Decorative header */}
274+
<div className="relative h-28 bg-gradient-to-br from-[#E8E8ED] via-[#EAEAF0] to-[#E0E0E8] overflow-hidden">
275+
{/* Abstract node graph pattern */}
276+
<svg
277+
className="absolute inset-0 w-full h-full opacity-[0.18]"
278+
viewBox="0 0 320 112"
279+
fill="none"
280+
>
281+
<title>Workflow pattern</title>
282+
<circle cx="80" cy="36" r="14" stroke="#888" strokeWidth="1.5" />
283+
<circle cx="160" cy="56" r="14" stroke="#888" strokeWidth="1.5" />
284+
<circle cx="240" cy="36" r="14" stroke="#888" strokeWidth="1.5" />
285+
<circle cx="200" cy="88" r="10" stroke="#888" strokeWidth="1.5" />
286+
<circle cx="120" cy="84" r="10" stroke="#888" strokeWidth="1.5" />
287+
<line x1="94" y1="36" x2="146" y2="56" stroke="#888" strokeWidth="1.2" />
288+
<line x1="174" y1="56" x2="226" y2="36" stroke="#888" strokeWidth="1.2" />
289+
<line x1="160" y1="70" x2="200" y2="78" stroke="#888" strokeWidth="1.2" />
290+
<line x1="160" y1="70" x2="120" y2="74" stroke="#888" strokeWidth="1.2" />
291+
</svg>
292+
<div className="absolute top-4 left-4">
293+
<div className="flex h-10 w-10 items-center justify-center rounded-[10px] bg-white/70 backdrop-blur-sm shadow-sm">
294+
<WorkflowIcon className="size-5 text-[#555]" />
295+
</div>
296+
</div>
322297

323-
{/* Menu on upper right of image */}
324-
<div className="absolute top-3 right-3 z-10">
298+
{/* Running indicator */}
299+
{wf.isRunning && (
300+
<div className="absolute top-3.5 right-12 bg-white/90 backdrop-blur-xs px-2 py-0.5 rounded-full flex items-center gap-1 shadow-xs border border-gray-100">
301+
<span className="relative flex h-1.5 w-1.5">
302+
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
303+
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-green-500" />
304+
</span>
305+
<span className="text-[10px] font-semibold text-green-700">
306+
Running
307+
</span>
308+
</div>
309+
)}
310+
311+
{/* Menu */}
312+
<div
313+
className="absolute top-3 right-3 z-10"
314+
onClick={(e) => e.stopPropagation()}
315+
onKeyDown={(e) => e.stopPropagation()}
316+
>
325317
<DropdownMenu>
326-
<DropdownMenuTrigger className="flex h-7 w-7 items-center justify-center rounded-md bg-white/80 backdrop-blur-xs text-gray-600 hover:bg-white hover:text-gray-900 shadow-xs cursor-pointer">
318+
<DropdownMenuTrigger className="flex h-7 w-7 items-center justify-center rounded-md bg-white/60 backdrop-blur-xs text-gray-500 hover:bg-white hover:text-gray-900 shadow-xs cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity">
327319
<MoreHorizontal className="size-4" />
328320
</DropdownMenuTrigger>
329321
<DropdownMenuContent align="end" sideOffset={4}>
@@ -365,18 +357,6 @@ export default function FlowPage() {
365357
</DropdownMenuContent>
366358
</DropdownMenu>
367359
</div>
368-
369-
{wf.isRunning && (
370-
<div className="absolute top-3 right-12 z-10 bg-white/90 backdrop-blur-xs px-2 py-0.5 rounded-full flex items-center gap-1 shadow-xs border border-gray-100">
371-
<span className="relative flex h-1.5 w-1.5">
372-
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
373-
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-green-500" />
374-
</span>
375-
<span className="text-[10px] font-semibold text-green-700">
376-
Running
377-
</span>
378-
</div>
379-
)}
380360
</div>
381361

382362
{/* Card content */}
@@ -387,22 +367,20 @@ export default function FlowPage() {
387367
className="h-7 text-sm border-gray-300 bg-white"
388368
value={renameValue}
389369
onChange={(e) => setRenameValue(e.target.value)}
370+
onClick={(e) => e.stopPropagation()}
390371
onKeyDown={(e) => {
372+
e.stopPropagation();
391373
if (e.key === "Enter") renameWorkflow(wf.id);
392374
if (e.key === "Escape") setRenaming(null);
393375
}}
394376
onBlur={() => renameWorkflow(wf.id)}
395377
/>
396378
) : (
397379
<>
398-
<button
399-
type="button"
400-
onClick={() => router.push(`/app/workflows/${wf.id}`)}
401-
className="text-[18px] font-medium text-gray-900 truncate block w-full text-left hover:text-indigo-600 transition-colors cursor-pointer"
402-
>
380+
<span className="text-[16px] font-medium text-gray-900 truncate block">
403381
{wf.name}
404-
</button>
405-
<span className="text-[14px] text-[#858589] mt-1 block font-normal">
382+
</span>
383+
<span className="text-[13px] text-[#858589] mt-1 block font-normal">
406384
Edited {timeAgo(wf.updatedAt)}
407385
</span>
408386
</>

‎app/app/layout.tsx‎

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import type { Metadata } from "next";
2-
import { AppSidebar } from "@/components/app-sidebar";
3-
import { PromoBanner } from "@/components/promo-banner";
4-
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
2+
import { Navbar } from "@/components/navbar";
53

64
export const metadata: Metadata = {
75
title: "Workflows",
@@ -11,12 +9,9 @@ export default function AppLayout({
119
children,
1210
}: Readonly<{ children: React.ReactNode }>) {
1311
return (
14-
<div className="flex flex-col h-screen overflow-hidden">
15-
<PromoBanner />
16-
<SidebarProvider className="flex-1 !min-h-0">
17-
<AppSidebar />
18-
<SidebarInset className="overflow-auto">{children}</SidebarInset>
19-
</SidebarProvider>
12+
<div className="flex flex-col h-screen overflow-hidden bg-gray-50/30 dark:bg-zinc-950">
13+
<Navbar />
14+
<main className="flex-1 overflow-auto">{children}</main>
2015
</div>
2116
);
2217
}

0 commit comments

Comments
 (0)