From fa28d27581dec275276f19f39cfb65bcbea2a851 Mon Sep 17 00:00:00 2001 From: Wes Date: Wed, 11 Mar 2026 09:56:46 -0700 Subject: [PATCH] Remove OS titlebar and add custom window chrome with drag support Use macOS overlay titlebar style to hide native window decorations while keeping traffic lights. Add drag regions to the sidebar header and content area, a fixed sidebar toggle next to the traffic lights, and the required Tauri permissions for window dragging/show/close. Also tightens border radii on home feed cards and simplifies the search shortcut badge. Co-Authored-By: Claude Opus 4.6 --- desktop/src-tauri/capabilities/default.json | 10 ++++++- desktop/src-tauri/src/lib.rs | 2 +- desktop/src-tauri/tauri.conf.json | 6 +++- desktop/src/app/App.tsx | 7 +++++ desktop/src/app/AppShell.tsx | 21 ++++++++++++-- desktop/src/features/chat/ui/ChatHeader.tsx | 13 +++++++-- desktop/src/features/home/ui/HomeView.tsx | 28 +++++++++---------- .../src/features/sidebar/ui/AppSidebar.tsx | 18 +++++++++--- desktop/src/shared/ui/sidebar.tsx | 6 ++-- 9 files changed, 82 insertions(+), 29 deletions(-) diff --git a/desktop/src-tauri/capabilities/default.json b/desktop/src-tauri/capabilities/default.json index 99de5006c40..9d1fb1f61ab 100644 --- a/desktop/src-tauri/capabilities/default.json +++ b/desktop/src-tauri/capabilities/default.json @@ -3,5 +3,13 @@ "identifier": "default", "description": "Capability for the main window", "windows": ["main"], - "permissions": ["core:default", "opener:default", "websocket:default"] + "permissions": [ + "core:default", + "core:window:allow-start-dragging", + "core:window:allow-show", + "core:window:allow-close", + "opener:default", + "websocket:default", + "window-state:default" + ] } diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index f19af15db2d..0aa110a8ac2 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -609,7 +609,7 @@ pub fn run() { .plugin( tauri_plugin_window_state::Builder::default() .with_state_flags( - StateFlags::SIZE | StateFlags::POSITION | StateFlags::MAXIMIZED, + StateFlags::all() & !StateFlags::VISIBLE, ) .build(), ) diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index bea12c01d48..d88824c5b67 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -14,7 +14,11 @@ { "title": "", "width": 800, - "height": 600 + "height": 600, + "visible": false, + "titleBarStyle": "Overlay", + "hiddenTitle": true, + "trafficLightPosition": { "x": 12, "y": 22 } } ], "security": { diff --git a/desktop/src/app/App.tsx b/desktop/src/app/App.tsx index 79fae3fed2f..048ad529bc2 100644 --- a/desktop/src/app/App.tsx +++ b/desktop/src/app/App.tsx @@ -1,5 +1,12 @@ +import { getCurrentWindow } from "@tauri-apps/api/window"; +import { useEffect } from "react"; + import { AppShell } from "@/app/AppShell"; export function App() { + useEffect(() => { + getCurrentWindow().show(); + }, []); + return ; } diff --git a/desktop/src/app/AppShell.tsx b/desktop/src/app/AppShell.tsx index b5528eb0640..8509bdf1f9d 100644 --- a/desktop/src/app/AppShell.tsx +++ b/desktop/src/app/AppShell.tsx @@ -1,3 +1,4 @@ +import { getCurrentWindow } from "@tauri-apps/api/window"; import * as React from "react"; import { Settings2 } from "lucide-react"; @@ -26,7 +27,11 @@ import { getEventById } from "@/shared/api/tauri"; import { useIdentityQuery } from "@/shared/api/hooks"; import type { RelayEvent, SearchHit } from "@/shared/api/types"; import { Button } from "@/shared/ui/button"; -import { SidebarInset, SidebarProvider } from "@/shared/ui/sidebar"; +import { + SidebarInset, + SidebarProvider, + SidebarTrigger, +} from "@/shared/ui/sidebar"; type AppView = "home" | "channel"; @@ -168,6 +173,7 @@ export function AppShell() { return ( + + {/* Drag strip covering the traffic-light inset area */} +
{ + if (e.button !== 0) return; + const target = e.target as HTMLElement; + if (target.closest('button, a, input, [role="button"]')) return; + e.preventDefault(); + getCurrentWindow().startDragging(); + }} + /> {selectedView === "home" ? ( ; } +function handlePointerDown(e: React.PointerEvent) { + if (e.button !== 0) return; + const target = e.target as HTMLElement; + if (target.closest('button, a, input, [role="button"]')) return; + e.preventDefault(); + getCurrentWindow().startDragging(); +} + export function ChatHeader({ actions, title, @@ -45,9 +53,8 @@ export function ChatHeader({
- -
diff --git a/desktop/src/features/home/ui/HomeView.tsx b/desktop/src/features/home/ui/HomeView.tsx index abc034d9504..6c6dbd3cd57 100644 --- a/desktop/src/features/home/ui/HomeView.tsx +++ b/desktop/src/features/home/ui/HomeView.tsx @@ -144,11 +144,11 @@ function FeedSection({ onOpenChannel, }: FeedSectionProps) { return ( -
+
-
+
@@ -166,7 +166,7 @@ function FeedSection({
{items.length === 0 ? ( -
+

{emptyTitle}

{emptyDescription} @@ -181,11 +181,11 @@ function FeedSection({ return (

-
+
@@ -271,7 +271,7 @@ function SummaryCard({ return (
-
+
{["first", "second", "third", "fourth"].map((item) => ( - + ))}
@@ -317,14 +317,14 @@ function HomeLoadingState() {
{["mentions", "actions", "activity", "agents"].map((section) => (
{["a", "b", "c"].map((row) => ( - + ))}
@@ -364,7 +364,7 @@ export function HomeView({ return (
-
+

Home feed unavailable

@@ -386,11 +386,11 @@ export function HomeView({ return (
-
+
-
+
diff --git a/desktop/src/features/sidebar/ui/AppSidebar.tsx b/desktop/src/features/sidebar/ui/AppSidebar.tsx index f3b419e8488..c49e9e51735 100644 --- a/desktop/src/features/sidebar/ui/AppSidebar.tsx +++ b/desktop/src/features/sidebar/ui/AppSidebar.tsx @@ -1,3 +1,4 @@ +import { getCurrentWindow } from "@tauri-apps/api/window"; import { CircleDot, FileText, @@ -294,13 +295,24 @@ export function AppSidebar({ } } + function handleDragPointerDown(e: React.PointerEvent) { + if (e.button !== 0) return; + const target = e.target as HTMLElement; + if (target.closest('button, a, input, [role="button"]')) return; + e.preventDefault(); + getCurrentWindow().startDragging(); + } + return ( - +
@@ -324,9 +336,7 @@ export function AppSidebar({ Search messages - - Cmd K - + ⌘K diff --git a/desktop/src/shared/ui/sidebar.tsx b/desktop/src/shared/ui/sidebar.tsx index b2cd9a44e0d..b068c5fa384 100644 --- a/desktop/src/shared/ui/sidebar.tsx +++ b/desktop/src/shared/ui/sidebar.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; -import { PanelLeft } from "lucide-react"; +import { PanelLeftClose, PanelLeftOpen } from "lucide-react"; import { cn } from "@/shared/lib/cn"; import { useIsMobile } from "@/shared/hooks/use-mobile"; @@ -271,7 +271,7 @@ const SidebarTrigger = React.forwardRef< React.ElementRef, React.ComponentProps >(({ className, onClick, ...props }, ref) => { - const { toggleSidebar } = useSidebar(); + const { toggleSidebar, open } = useSidebar(); return ( );