Download components/chat/AppShell.tsx from Etiya/d2l-ui: direct link, hf CLI and curl.
- Browser
- Download file 1.92 kB
-
https://huggingface.co/spaces/Etiya/d2l-ui/resolve/main/components/chat/AppShell.tsx
- Command line
-
hf download hf://spaces/Etiya/d2l-ui/components/chat/AppShell.tsx
-
curl -L -o AppShell.tsx https://huggingface.co/spaces/Etiya/d2l-ui/resolve/main/components/chat/AppShell.tsx
1.92 kB
| "use client"; | |
| import { Sidebar } from "./Sidebar"; | |
| import { TopBar } from "./TopBar"; | |
| import { Aurora } from "./Aurora"; | |
| import { useChatStore } from "@/lib/chatStore"; | |
| import { useBackendSync } from "@/lib/useBackendSync"; | |
| import clsx from "clsx"; | |
| import { usePathname } from "next/navigation"; | |
| import { useEffect } from "react"; | |
| export function AppShell({ children }: { children: React.ReactNode }) { | |
| const sidebarOpen = useChatStore((s) => s.sidebarOpen); | |
| const hydrated = useChatStore((s) => s.hydrated); | |
| const pathname = usePathname(); | |
| const conversations = useChatStore((s) => s.conversations); | |
| const activeId = useChatStore((s) => s.activeId); | |
| const newConversation = useChatStore((s) => s.newConversation); | |
| // Backend hydration + auto-save (debounced PUT to /conversations) | |
| useBackendSync(); | |
| // Ensure there is always at least one conversation when on chat route. | |
| // Wait until hydration completes so we don't create a placeholder before | |
| // the remote state arrives (which would cause a flash + redundant save). | |
| useEffect(() => { | |
| if (pathname !== "/") return; | |
| if (!hydrated) return; | |
| const hasAny = Object.keys(conversations).length > 0; | |
| const hasActive = activeId && conversations[activeId]; | |
| if (!hasAny || !hasActive) newConversation(); | |
| }, [pathname, hydrated, conversations, activeId, newConversation]); | |
| return ( | |
| <div className="relative h-screen flex flex-col overflow-hidden"> | |
| {/* Atmospheric background — fixed, behind everything */} | |
| <Aurora /> | |
| <TopBar /> | |
| <div className="relative z-10 flex-1 flex overflow-hidden min-h-0"> | |
| <Sidebar /> | |
| <main | |
| className={clsx( | |
| "flex-1 flex flex-col min-w-0 min-h-0 transition-[margin] duration-300 ease-atelier", | |
| sidebarOpen ? "md:ml-0" : "md:ml-0" | |
| )} | |
| > | |
| {children} | |
| </main> | |
| </div> | |
| </div> | |
| ); | |
| } | |