diff --git a/apps/next/src/app/(home)/page.tsx b/apps/next/src/app/(home)/page.tsx index bb02face8d060386bc295114f98bf67e10d8908f..a777163a81a20f42f1438ef330d7ecd3d01c37b8 100644 --- a/apps/next/src/app/(home)/page.tsx +++ b/apps/next/src/app/(home)/page.tsx @@ -1,5 +1,6 @@ import { CodeBlock } from "@/components/code-block"; import { Contributing } from "@/components/contribution"; +import { CreateAppAnimation } from "@/components/create-app-animation"; import { Feature } from "@/components/feature"; import { NpmInstall } from "@/components/npm-install"; import { TextEffect } from "@/components/text-effect"; @@ -72,37 +73,9 @@ await agent.chat('...');`} heading="CLI for starting RAG app with one line" description="A command line tool to generate LlamaIndex apps, the easiest way to get started with LlamaIndex." > - <CodeBlock - code="npx create-llama@latest" - lang="bash" - wrapper={{ - title: "Terminal", - allowCopy: true, - }} - /> - <pre className="grid grid-cols-1 rounded-lg border bg-card p-4 text-xs leading-loose"> - <code> - <div>? What app do you want to build?</div> - <ul> - <li>❯ Agentic RAG</li> - <li> Data Scientist</li> - <li> Financial Report Generator (using Workflows)</li> - <li> Code Artifact Agent</li> - <li> Structured extraction</li> - </ul> - </code> - <code> - ? What language do you want to use? - <ul> - <li>❯ TypeScript</li> - <li> Python</li> - </ul> - </code> - <code className="text-muted-foreground">{`Initializing project with template...`}</code> - <code className="text-green-500"> - Success! Created app at /path/to/app - </code> - </pre> + <div className="my-6"> + <CreateAppAnimation /> + </div> </Feature> </div> <Contributing /> diff --git a/apps/next/src/components/create-app-animation.tsx b/apps/next/src/components/create-app-animation.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1811d99394648c7f7535fbdd49b4c6f57fa60c52 --- /dev/null +++ b/apps/next/src/components/create-app-animation.tsx @@ -0,0 +1,118 @@ +"use client"; +import { cn } from "@/lib/utils"; +import { TerminalIcon } from "lucide-react"; +import { + Fragment, + HTMLAttributes, + ReactElement, + useEffect, + useState, +} from "react"; + +export function CreateAppAnimation(): React.ReactElement { + const installCmd = "npx create-llama@latest"; + const tickTime = 100; + const timeCommandEnter = installCmd.length; + const timeCommandRun = timeCommandEnter + 3; + const timeCommandEnd = timeCommandRun + 3; + const timeWindowOpen = timeCommandEnd + 1; + const timeEnd = timeWindowOpen + 1; + + const [tick, setTick] = useState(timeEnd); + + useEffect(() => { + const timer = setInterval(() => { + setTick((prev) => (prev >= timeEnd ? prev : prev + 1)); + }, tickTime); + + return () => { + clearInterval(timer); + }; + }, [timeEnd]); + + const lines: ReactElement[] = []; + + lines.push( + <span key="command_type"> + {installCmd.substring(0, tick)} + {tick < timeCommandEnter && ( + <div className="inline-block h-3 w-1 animate-pulse bg-white" /> + )} + </span>, + ); + + if (tick >= timeCommandEnter) { + lines.push(<span key="space"> </span>); + } + + if (tick > timeCommandRun) + lines.push( + <Fragment key="command_response"> + <span className="font-bold">┌ Create Llama</span> + <span>│</span> + {tick > timeCommandRun + 1 && ( + <> + <span className="font-bold">◇ What is your project named?</span> + <span>│ my-app</span> + </> + )} + {tick > timeCommandRun + 2 && ( + <> + <span>│</span> + <span className="font-bold">◆ What app do you want to build?</span> + </> + )} + {tick > timeCommandRun + 3 && ( + <> + <span>│ ● Agentic RAG</span> + <span>│ ○ Data Scientist</span> + </> + )} + </Fragment>, + ); + + return ( + <div + className="relative" + onMouseEnter={() => { + if (tick >= timeEnd) { + setTick(0); + } + }} + > + {tick > timeWindowOpen && ( + <LaunchAppWindow className="absolute bottom-5 right-4 z-10 animate-in fade-in slide-in-from-top-10" /> + )} + <pre className="overflow-hidden rounded-xl border text-xs"> + <div className="flex flex-row items-center gap-2 border-b px-4 py-2"> + <TerminalIcon className="size-4" />{" "} + <span className="font-bold">Terminal</span> + <div className="grow" /> + <div className="size-2 rounded-full bg-red-400" /> + </div> + <div className="min-h-[200px] bg-gradient-to-b from-fd-secondary [mask-image:linear-gradient(to_bottom,white,transparent)]"> + <code className="grid p-4">{lines}</code> + </div> + </pre> + </div> + ); +} + +function LaunchAppWindow( + props: HTMLAttributes<HTMLDivElement>, +): React.ReactElement { + return ( + <div + {...props} + className={cn( + "overflow-hidden rounded-md border bg-fd-background shadow-xl", + props.className, + )} + > + <div className="relative flex h-6 flex-row items-center border-b bg-fd-muted px-4 text-xs text-fd-muted-foreground"> + <p className="absolute inset-x-0 text-center">localhost:8080</p> + </div> + <div className="p-4 text-sm">New App launched!</div> + </div> + ); +}