1import { MessageSquareDashedIcon, PlusIcon } from "lucide-react";
2import { useCallback } from "react";
3
4import { openCommandPalette } from "../commandPaletteBus";
5import { isElectron } from "../env";
6import { useScratchProject } from "../hooks/useScratchProject";
7import { usePrimaryEnvironmentId } from "../state/environments";
8import { Button } from "./ui/button";
9import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "./ui/empty";
10import { SidebarInset } from "./ui/sidebar";
11import { WorkspacePageHeader } from "./WorkspacePageHeader";
12
13export function NoProjectsHero() {
14 const openAddProject = useCallback(() => openCommandPalette({ open: "add-project" }), []);
15 const primaryEnvironmentId = usePrimaryEnvironmentId();
16 const { scratchEnvironmentId, startScratchThread } = useScratchProject();
17 const scratchTargetEnvironmentId = scratchEnvironmentId(primaryEnvironmentId);
18
19 return (
20 <SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none">
21 <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden bg-background">
22 {/* The desktop window only moves where CSS opts in, so keep a titlebar strip. */}
23 {isElectron ? <WorkspacePageHeader electron /> : null}
24 <Empty size="hero" className="flex-1">
25 <div className="w-full max-w-lg px-8 py-12">
26 <EmptyHeader className="max-w-none">
27 <EmptyTitle>What should we work on?</EmptyTitle>
28 <EmptyDescription>
29 {scratchTargetEnvironmentId === null
30 ? "Add a project to start your first thread."
31 : "Add a project, or start without one."}
32 </EmptyDescription>
33 <div className="mt-6 flex justify-center gap-2">
34 <Button size="sm" onClick={openAddProject}>
35 <PlusIcon className="size-4" />
36 Add project
37 </Button>
38 {scratchTargetEnvironmentId === null ? null : (
39 <Button
40 size="sm"
41 variant="outline"
42 onClick={() => void startScratchThread(scratchTargetEnvironmentId)}
43 >
44 <MessageSquareDashedIcon className="size-4" />
45 Start without a project
46 </Button>
47 )}
48 </div>
49 </EmptyHeader>
50 </div>
51 </Empty>
52 </div>
53 </SidebarInset>
54 );
55}