Files
inkreach-agent/apps/desktop/src/renderer/src/components/TitleBar.tsx
T

85 lines
3.6 KiB
TypeScript

import { useEffect, useState, type JSX, type ReactNode } from 'react'
import { LuPanelRight } from 'react-icons/lu'
/**
* 自绘标题栏(配合主进程 titleBarStyle:'hidden')。
* 整条是拖拽区;左上角展示当前会话/插件名称(无名称时显示「新会话」);
* title 之后可挂 extra 槽(插件状态胶囊);右侧自绘窗口控制按钮(最小化/
* 最大化还原/关闭),高度 40px。不使用系统 WCO overlay —— 其原生背景会盖住标题栏分隔线。
*/
export function TitleBar({
title,
panelOpen,
onTogglePanel,
extra
}: {
title?: string
panelOpen: boolean
onTogglePanel: () => void
/** 标题右侧插槽(插件状态胶囊等;聊天/插件视图下均可见) */
extra?: ReactNode
}): JSX.Element {
const name = title?.trim()
const [maximized, setMaximized] = useState(false)
useEffect(() => window.api.onWindowState((maximized) => setMaximized(maximized)), [])
return (
<div className="relative z-20 flex h-10 shrink-0 select-none items-center border-b border-line bg-surface pl-4 [-webkit-app-region:drag]">
<div className="min-w-0 truncate text-[12.5px] font-medium text-ink">{name || '新会话'}</div>
{extra && <div className="ml-3 flex shrink-0 items-center [-webkit-app-region:no-drag]">{extra}</div>}
<div className="ml-auto flex h-full shrink-0 items-center gap-1 pr-1.5 [-webkit-app-region:no-drag]">
<button
type="button"
aria-label={panelOpen ? '关闭侧边面板' : '打开侧边面板'}
title="侧边面板"
onClick={onTogglePanel}
className={`flex h-7 w-[30px] items-center justify-center rounded transition-colors ${
panelOpen ? 'bg-accent-tint text-accent-ink' : 'text-ink-3 hover:bg-hover hover:text-ink-2'
}`}
>
<LuPanelRight size={14} />
</button>
</div>
<div className="flex h-full shrink-0 [-webkit-app-region:no-drag]">
<button
type="button"
aria-label="最小化"
onClick={() => void window.api.minimize()}
className="flex h-full w-[46px] items-center justify-center text-ink-3 transition-colors hover:bg-hover hover:text-ink-2"
>
<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden>
<path d="M0 5h10" stroke="currentColor" strokeWidth="1" />
</svg>
</button>
<button
type="button"
aria-label={maximized ? '还原' : '最大化'}
onClick={() => void window.api.toggleMaximize()}
className="flex h-full w-[46px] items-center justify-center text-ink-3 transition-colors hover:bg-hover hover:text-ink-2"
>
{maximized ? (
<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden>
<path d="M2.5 2.5V0h7.5v7.5H7.5M0 2.5h7.5V10H0z" fill="none" stroke="currentColor" strokeWidth="1" />
</svg>
) : (
<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden>
<path d="M.5.5h9v9H.5z" fill="none" stroke="currentColor" strokeWidth="1" />
</svg>
)}
</button>
<button
type="button"
aria-label="关闭"
onClick={() => void window.api.close()}
className="flex h-full w-[46px] items-center justify-center text-ink-3 transition-colors hover:bg-[#e81123] hover:text-page"
>
<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden>
<path d="M0 0l10 10M10 0L0 10" stroke="currentColor" strokeWidth="1" />
</svg>
</button>
</div>
</div>
)
}