diff --git a/apps/x/apps/main/src/main.ts b/apps/x/apps/main/src/main.ts index a77a8f7b..d2ad14e1 100644 --- a/apps/x/apps/main/src/main.ts +++ b/apps/x/apps/main/src/main.ts @@ -71,6 +71,8 @@ function createWindow() { height: 800, show: false, // Don't show until ready backgroundColor: "#252525", // Prevent white flash (matches dark mode) + titleBarStyle: "hiddenInset", + trafficLightPosition: { x: 12, y: 12 }, webPreferences: { // IMPORTANT: keep Node out of renderer nodeIntegration: false, diff --git a/apps/x/apps/renderer/src/App.css b/apps/x/apps/renderer/src/App.css index 64d2b9a3..991236ea 100644 --- a/apps/x/apps/renderer/src/App.css +++ b/apps/x/apps/renderer/src/App.css @@ -255,6 +255,15 @@ } } +/* Titlebar drag regions for frameless window */ +.titlebar-drag-region { + -webkit-app-region: drag; +} + +.titlebar-no-drag { + -webkit-app-region: no-drag; +} + .graph-view { background-color: var(--background); user-select: none; diff --git a/apps/x/apps/renderer/src/App.tsx b/apps/x/apps/renderer/src/App.tsx index 56d953e3..5023da09 100644 --- a/apps/x/apps/renderer/src/App.tsx +++ b/apps/x/apps/renderer/src/App.tsx @@ -6,7 +6,7 @@ import type { LanguageModelUsage, ToolUIPart } from 'ai'; import './App.css' import z from 'zod'; import { Button } from './components/ui/button'; -import { CheckIcon, LoaderIcon, ArrowUp, PanelRightIcon, SquarePen, Square } from 'lucide-react'; +import { CheckIcon, LoaderIcon, ArrowUp, PanelLeftIcon, PanelRightIcon, SquarePen, Square } from 'lucide-react'; import { cn } from '@/lib/utils'; import { MarkdownEditor } from './components/markdown-editor'; import { ChatInputBar } from './components/chat-button'; @@ -43,7 +43,7 @@ import { ToolPermissionRequestEvent, AskHumanRequestEvent } from '@x/shared/src/ import { SidebarInset, SidebarProvider, - SidebarTrigger, + useSidebar, } from "@/components/ui/sidebar" import { TooltipProvider } from "@/components/ui/tooltip" import { Separator } from "@/components/ui/separator" @@ -443,6 +443,46 @@ function ChatInputWithMentions({ ) } +/** Traffic light placeholders + toggle button, fixed next to macOS traffic lights */ +function FixedSidebarToggle() { + const { toggleSidebar } = useSidebar() + return ( +
+ {/* Placeholder dots that show through when traffic lights are hidden (window unfocused) */} +
+
+
+
+
+ {/* Sidebar toggle */} + +
+ ) +} + +/** Main content header that adjusts padding based on sidebar state */ +function ContentHeader({ children }: { children: React.ReactNode }) { + const { state } = useSidebar() + const isCollapsed = state === "collapsed" + return ( +
+ {children} +
+ ) +} + function App() { // File browser state (for Knowledge section) const [selectedPath, setSelectedPath] = useState(null) @@ -1816,10 +1856,8 @@ function App() { selectedBackgroundTask={selectedBackgroundTask} /> - {/* Header with sidebar triggers */} -
- - + {/* Header - also serves as titlebar drag region, adjusts padding when sidebar collapsed */} + {headerTitle} @@ -1848,7 +1886,7 @@ function App() { setIsChatSidebarOpen(true) } }} - className="text-foreground gap-1.5" + className="titlebar-no-drag text-foreground gap-1.5" > New Chat @@ -1859,7 +1897,7 @@ function App() { variant="ghost" size="sm" onClick={() => setIsGraphOpen(false)} - className="text-foreground" + className="titlebar-no-drag text-foreground" > Close Graph @@ -1871,14 +1909,14 @@ function App() { variant="ghost" size="icon" onClick={() => setIsChatSidebarOpen(!isChatSidebarOpen)} - className="size-7 -mr-1" + className="titlebar-no-drag size-7 -mr-1" > Toggle Chat Sidebar )} -
+ {isGraphOpen ? (
@@ -2056,6 +2094,8 @@ function App() { onAskHumanResponse={handleAskHumanResponse} /> )} + {/* Rendered last so its no-drag region paints over the sidebar drag region */} + {/* Floating chat input - shown when viewing files/graph and chat sidebar is closed */} diff --git a/apps/x/apps/renderer/src/components/chat-sidebar.tsx b/apps/x/apps/renderer/src/components/chat-sidebar.tsx index b5b32e09..876c7830 100644 --- a/apps/x/apps/renderer/src/components/chat-sidebar.tsx +++ b/apps/x/apps/renderer/src/components/chat-sidebar.tsx @@ -458,7 +458,7 @@ export function ChatSidebar({ {showContent && ( <> {/* Header - minimal, expand and new chat buttons */} -
+
{onOpenFullScreen && ( diff --git a/apps/x/apps/renderer/src/components/sidebar-content.tsx b/apps/x/apps/renderer/src/components/sidebar-content.tsx index 4f7e65bc..bc6421b1 100644 --- a/apps/x/apps/renderer/src/components/sidebar-content.tsx +++ b/apps/x/apps/renderer/src/components/sidebar-content.tsx @@ -267,9 +267,12 @@ export function SidebarContentPanel({ return ( - + + {/* Top spacer to clear the traffic lights + fixed toggle row */} +
+ {/* Tab switcher - centered below the traffic lights row */}
-
+
{sectionTabs.map((tab) => (