From 6bfabdb7010dcd2ee9531932f8e4ecc63d5cc429 Mon Sep 17 00:00:00 2001 From: Nexus Dev Date: Wed, 1 Apr 2026 16:49:11 +0000 Subject: [PATCH] feat(21-04): create ChatPanel shell and wire into Layout and main.tsx - ChatPanel: 380px right-side drawer with transition-[width] and hidden md:flex - Two-column skeleton: 160px conversation list + flex thread area with ChatInput - Layout: import ChatPanel, MessageSquare, useChatPanel; add chat toggle button - Layout: useEffect closes PropertiesPanel when chatOpen becomes true - Layout: ChatPanel rendered before PropertiesPanel in flex row - main.tsx: ChatPanelProvider wrapping app inside PanelProvider --- ui/src/components/ChatPanel.tsx | 63 +++++++++++++++++++++++++++++++++ ui/src/components/Layout.tsx | 30 ++++++++++++++-- ui/src/main.tsx | 13 ++++--- 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 ui/src/components/ChatPanel.tsx diff --git a/ui/src/components/ChatPanel.tsx b/ui/src/components/ChatPanel.tsx new file mode 100644 index 00000000..e0f2d646 --- /dev/null +++ b/ui/src/components/ChatPanel.tsx @@ -0,0 +1,63 @@ +import { X } from "lucide-react"; +import { useChatPanel } from "../context/ChatPanelContext"; +import { ChatInput } from "./ChatInput"; +import { Button } from "@/components/ui/button"; +import { ScrollArea } from "@/components/ui/scroll-area"; + +export function ChatPanel() { + const { chatOpen, setChatOpen } = useChatPanel(); + + return ( + + ); +} diff --git a/ui/src/components/Layout.tsx b/ui/src/components/Layout.tsx index 6a57e5a1..6183b821 100644 --- a/ui/src/components/Layout.tsx +++ b/ui/src/components/Layout.tsx @@ -1,11 +1,12 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { BookOpen, Moon, Settings, Sun } from "lucide-react"; +import { BookOpen, MessageSquare, Moon, Settings, Sun } from "lucide-react"; import { Link, Outlet, useLocation, useNavigate, useParams } from "@/lib/router"; import { CompanyRail } from "./CompanyRail"; import { Sidebar } from "./Sidebar"; import { InstanceSidebar } from "./InstanceSidebar"; import { BreadcrumbBar } from "./BreadcrumbBar"; +import { ChatPanel } from "./ChatPanel"; import { PropertiesPanel } from "./PropertiesPanel"; import { CommandPalette } from "./CommandPalette"; import { NewIssueDialog } from "./NewIssueDialog"; @@ -18,6 +19,7 @@ import { WorktreeBanner } from "./WorktreeBanner"; import { DevRestartBanner } from "./DevRestartBanner"; import { useDialog } from "../context/DialogContext"; import { usePanel } from "../context/PanelContext"; +import { useChatPanel } from "../context/ChatPanelContext"; import { useCompany } from "../context/CompanyContext"; import { useSidebar } from "../context/SidebarContext"; import { useTheme, THEME_META } from "../context/ThemeContext"; @@ -49,7 +51,8 @@ function readRememberedInstanceSettingsPath(): string { export function Layout() { const { sidebarOpen, setSidebarOpen, toggleSidebar, isMobile } = useSidebar(); const { openNewIssue, openOnboarding } = useDialog(); - const { togglePanelVisible } = usePanel(); + const { togglePanelVisible, setPanelVisible } = usePanel(); + const { chatOpen, toggleChat } = useChatPanel(); const { companies, loading: companiesLoading, @@ -144,6 +147,13 @@ export function Layout() { const togglePanel = togglePanelVisible; + // Close PropertiesPanel when chat panel opens + useEffect(() => { + if (chatOpen) { + setPanelVisible(false); + } + }, [chatOpen, setPanelVisible]); + useCompanyPageMemory(); useKeyboardShortcuts({ @@ -389,6 +399,21 @@ export function Layout() { + + + + + {chatOpen ? "Close chat" : "Open chat"} +