Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Haze <hazeone@users.noreply.github.com>
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
/**
|
|
* TitleBar Component
|
|
* macOS: empty drag region (native traffic lights handled by hiddenInset).
|
|
* Windows: drag region with custom minimize/maximize/close controls.
|
|
* Linux: use native window chrome (no custom title bar).
|
|
*/
|
|
import { useState, useEffect } from 'react';
|
|
import { Minus, Square, X, Copy } from 'lucide-react';
|
|
import { invokeIpc } from '@/lib/api-client';
|
|
|
|
export function TitleBar() {
|
|
const platform = window.electron?.platform;
|
|
|
|
if (platform === 'darwin') {
|
|
// macOS: just a drag region, traffic lights are native
|
|
return <div className="drag-region h-10 shrink-0 border-b bg-background" />;
|
|
}
|
|
|
|
// Linux keeps the native frame/title bar for better IME compatibility.
|
|
if (platform !== 'win32') {
|
|
return null;
|
|
}
|
|
|
|
return <WindowsTitleBar />;
|
|
}
|
|
|
|
function WindowsTitleBar() {
|
|
const [maximized, setMaximized] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Check initial state
|
|
invokeIpc('window:isMaximized').then((val) => {
|
|
setMaximized(val as boolean);
|
|
});
|
|
}, []);
|
|
|
|
const handleMinimize = () => {
|
|
invokeIpc('window:minimize');
|
|
};
|
|
|
|
const handleMaximize = () => {
|
|
invokeIpc('window:maximize').then(() => {
|
|
invokeIpc('window:isMaximized').then((val) => {
|
|
setMaximized(val as boolean);
|
|
});
|
|
});
|
|
};
|
|
|
|
const handleClose = () => {
|
|
invokeIpc('window:close');
|
|
};
|
|
|
|
return (
|
|
<div className="drag-region flex h-10 shrink-0 items-center justify-end border-b bg-background">
|
|
|
|
{/* Right: Window Controls */}
|
|
<div className="no-drag flex h-full">
|
|
<button
|
|
onClick={handleMinimize}
|
|
className="flex h-full w-11 items-center justify-center text-muted-foreground hover:bg-accent transition-colors"
|
|
title="Minimize"
|
|
>
|
|
<Minus className="h-4 w-4" />
|
|
</button>
|
|
<button
|
|
onClick={handleMaximize}
|
|
className="flex h-full w-11 items-center justify-center text-muted-foreground hover:bg-accent transition-colors"
|
|
title={maximized ? 'Restore' : 'Maximize'}
|
|
>
|
|
{maximized ? <Copy className="h-3.5 w-3.5" /> : <Square className="h-3.5 w-3.5" />}
|
|
</button>
|
|
<button
|
|
onClick={handleClose}
|
|
className="flex h-full w-11 items-center justify-center text-muted-foreground hover:bg-red-500 hover:text-white transition-colors"
|
|
title="Close"
|
|
>
|
|
<X className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|