diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 9fdef43..8f22442 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -16,7 +16,8 @@
"width": 1200,
"height": 800,
"minWidth": 800,
- "minHeight": 600
+ "minHeight": 600,
+ "decorations": false
}
],
"security": {
diff --git a/src/components/layout/TopBar.tsx b/src/components/layout/TopBar.tsx
index 083d855..3e452f7 100644
--- a/src/components/layout/TopBar.tsx
+++ b/src/components/layout/TopBar.tsx
@@ -17,6 +17,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { useAppStore } from "@/stores/app-store";
import { useBoardStore } from "@/stores/board-store";
+import { WindowControls } from "@/components/layout/WindowControls";
export function TopBar() {
const view = useAppStore((s) => s.view);
@@ -238,6 +239,7 @@ export function TopBar() {
Settings
+
);
diff --git a/src/components/layout/WindowControls.tsx b/src/components/layout/WindowControls.tsx
new file mode 100644
index 0000000..f1c46c3
--- /dev/null
+++ b/src/components/layout/WindowControls.tsx
@@ -0,0 +1,73 @@
+import { useState, useEffect } from "react";
+import { getCurrentWindow } from "@tauri-apps/api/window";
+import { motion } from "framer-motion";
+import { Minus, Square, Copy, X } from "lucide-react";
+import { springs } from "@/lib/motion";
+
+export function WindowControls() {
+ const [isMaximized, setIsMaximized] = useState(false);
+
+ useEffect(() => {
+ const appWindow = getCurrentWindow();
+
+ appWindow.isMaximized().then(setIsMaximized);
+
+ const unlisten = appWindow.onResized(async () => {
+ const maximized = await appWindow.isMaximized();
+ setIsMaximized(maximized);
+ });
+
+ return () => {
+ unlisten.then((fn) => fn());
+ };
+ }, []);
+
+ const appWindow = getCurrentWindow();
+
+ return (
+
+ {/* Separator */}
+
+
+ {/* Minimize */}
+
appWindow.minimize()}
+ className="flex size-8 items-center justify-center rounded-md text-pylon-text-secondary transition-colors hover:bg-pylon-accent/10 hover:text-pylon-text"
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ transition={springs.snappy}
+ aria-label="Minimize"
+ >
+
+
+
+ {/* Maximize / Restore */}
+
appWindow.toggleMaximize()}
+ className="flex size-8 items-center justify-center rounded-md text-pylon-text-secondary transition-colors hover:bg-pylon-accent/10 hover:text-pylon-text"
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ transition={springs.snappy}
+ aria-label={isMaximized ? "Restore" : "Maximize"}
+ >
+ {isMaximized ? (
+
+ ) : (
+
+ )}
+
+
+ {/* Close */}
+
appWindow.close()}
+ className="flex size-8 items-center justify-center rounded-md text-pylon-text-secondary transition-colors hover:bg-pylon-danger/15 hover:text-pylon-danger"
+ whileHover={{ scale: 1.1 }}
+ whileTap={{ scale: 0.9 }}
+ transition={springs.snappy}
+ aria-label="Close"
+ >
+
+
+
+ );
+}