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 99de5006c..9d1fb1f61 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 f19af15db..0aa110a8a 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 bea12c01d..d88824c5b 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 79fae3fed..048ad529b 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 b5528eb06..8509bdf1f 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 abc034d95..6c6dbd3cd 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 f3b419e84..c49e9e517 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 b2cd9a44e..b068c5fa3 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 ( );