You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
8.2 KiB
195 lines
8.2 KiB
"use client";
|
|
|
|
interface QuickstartInitialViewProps {
|
|
onSelectBlankCanvas: () => void;
|
|
onSelectTemplates: () => void;
|
|
onSelectVibe: () => void;
|
|
onSelectLoad: () => void;
|
|
}
|
|
|
|
export function QuickstartInitialView({
|
|
onSelectBlankCanvas,
|
|
onSelectTemplates,
|
|
onSelectVibe,
|
|
onSelectLoad,
|
|
}: QuickstartInitialViewProps) {
|
|
return (
|
|
<div className="p-8">
|
|
<div className="flex gap-10">
|
|
{/* Left column - Info */}
|
|
<div className="flex-1 flex flex-col">
|
|
<div className="mb-4">
|
|
<div className="flex items-center gap-2">
|
|
<img src="/banana_icon.png" alt="" className="w-7 h-7" />
|
|
<h1 className="text-2xl font-medium text-neutral-100">
|
|
Node Banana
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
|
|
<p className="text-sm text-neutral-400 leading-relaxed mb-6">
|
|
A node based workflow editor for AI image generation. Connect nodes to build pipelines that transform and generate images.
|
|
</p>
|
|
|
|
<div className="flex flex-col gap-2.5 mt-auto">
|
|
<a
|
|
href="https://node-banana-docs.vercel.app/"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 text-sm text-neutral-400 hover:text-neutral-200 transition-colors"
|
|
>
|
|
<svg
|
|
className="w-4 h-4"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
strokeWidth={1.5}
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"
|
|
/>
|
|
</svg>
|
|
Docs
|
|
</a>
|
|
<a
|
|
href="https://discord.com/invite/89Nr6EKkTf"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 text-sm text-neutral-400 hover:text-neutral-200 transition-colors"
|
|
>
|
|
<svg
|
|
className="w-4 h-4"
|
|
fill="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028a14.09 14.09 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z" />
|
|
</svg>
|
|
Discord
|
|
</a>
|
|
<a
|
|
href="https://x.com/ReflctWillie"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 text-sm text-neutral-400 hover:text-neutral-200 transition-colors"
|
|
>
|
|
<svg
|
|
className="w-4 h-4"
|
|
fill="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
</svg>
|
|
Willie
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right column - Options */}
|
|
<div className="flex-1 flex flex-col gap-2 justify-end">
|
|
<OptionButton
|
|
onClick={onSelectBlankCanvas}
|
|
icon={
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M12 4.5v15m7.5-7.5h-15"
|
|
/>
|
|
}
|
|
title="Blank canvas"
|
|
description="Start from scratch"
|
|
/>
|
|
|
|
<OptionButton
|
|
onClick={onSelectLoad}
|
|
icon={
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 00-1.883 2.542l.857 6a2.25 2.25 0 002.227 1.932H19.05a2.25 2.25 0 002.227-1.932l.857-6a2.25 2.25 0 00-1.883-2.542m-16.5 0V6A2.25 2.25 0 016 3.75h3.879a1.5 1.5 0 011.06.44l2.122 2.12a1.5 1.5 0 001.06.44H18A2.25 2.25 0 0120.25 9v.776"
|
|
/>
|
|
}
|
|
title="Load workflow"
|
|
description="Open existing file"
|
|
/>
|
|
|
|
<OptionButton
|
|
onClick={onSelectTemplates}
|
|
icon={
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z"
|
|
/>
|
|
}
|
|
title="Templates"
|
|
description="Pre-built workflows"
|
|
/>
|
|
|
|
<OptionButton
|
|
onClick={onSelectVibe}
|
|
icon={
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z"
|
|
/>
|
|
}
|
|
title="Prompt a workflow"
|
|
description="Describe what you want"
|
|
badge="Beta"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function OptionButton({
|
|
onClick,
|
|
icon,
|
|
title,
|
|
description,
|
|
badge,
|
|
}: {
|
|
onClick: () => void;
|
|
icon: React.ReactNode;
|
|
title: string;
|
|
description: string;
|
|
badge?: string;
|
|
}) {
|
|
return (
|
|
<button
|
|
onClick={onClick}
|
|
className="group text-left p-4 rounded-lg border border-neutral-700/50 hover:border-neutral-600 hover:bg-neutral-800/40 transition-all duration-150"
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-md bg-neutral-700/50 flex items-center justify-center flex-shrink-0 group-hover:bg-neutral-700 transition-colors">
|
|
<svg
|
|
className="w-4 h-4 text-neutral-400 group-hover:text-neutral-300 transition-colors"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
strokeWidth={1.5}
|
|
>
|
|
{icon}
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<div className="flex items-center gap-2">
|
|
<h3 className="text-sm font-medium text-neutral-200 group-hover:text-neutral-100 transition-colors">
|
|
{title}
|
|
</h3>
|
|
{badge && (
|
|
<span className="px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide rounded bg-blue-500/20 text-blue-400">
|
|
{badge}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<p className="text-xs text-neutral-500">{description}</p>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
);
|
|
}
|
|
|