feat(agent): optimize agent panel header and functionality layout for improved space efficiency

This commit is contained in:
HouYunFei
2026-07-29 17:08:17 +08:00
parent 8babf7faa0
commit 7a48f441cf
5 changed files with 20 additions and 26 deletions
@@ -2,13 +2,14 @@ import type { ReactNode } from "react";
import { canvasThemes } from "@/lib/canvas-theme";
export function AgentPanelTabs<T extends string>({ value, items, theme, right, onChange }: { value: T; items: { value: T; label: string; icon?: ReactNode; count?: number }[]; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; right?: ReactNode; onChange: (value: T) => void }) {
export function AgentPanelTabs<T extends string>({ value, items, theme, leading, right, onChange }: { value: T; items: { value: T; label: string; icon?: ReactNode; count?: number }[]; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; leading?: ReactNode; right?: ReactNode; onChange: (value: T) => void }) {
return (
<div className="border-b px-3" style={{ borderColor: theme.node.stroke }}>
<div className="flex min-h-11 items-center justify-between gap-3">
<div className="flex h-12 items-center justify-between gap-3">
{leading ? <div className="flex shrink-0 items-center">{leading}</div> : null}
<nav className="thin-scrollbar flex min-w-0 flex-1 items-center gap-3 overflow-x-auto text-sm" role="tablist" aria-label="Agent 面板">
{items.map((item) => (
<button key={item.value} type="button" role="tab" aria-selected={value === item.value} className={`inline-flex h-11 shrink-0 items-center gap-1.5 border-b-2 px-0.5 transition ${value === item.value ? "font-medium" : "font-normal"}`} style={{ borderColor: value === item.value ? theme.node.text : "transparent", color: value === item.value ? theme.node.text : theme.node.muted }} onClick={() => onChange(item.value)}>
<button key={item.value} type="button" role="tab" aria-selected={value === item.value} className={`inline-flex h-12 shrink-0 items-center gap-1.5 border-b-2 px-0.5 transition ${value === item.value ? "font-medium" : "font-normal"}`} style={{ borderColor: value === item.value ? theme.node.text : "transparent", color: value === item.value ? theme.node.text : theme.node.muted }} onClick={() => onChange(item.value)}>
{item.icon}
{item.label}{item.count ? ` ${item.count}` : ""}
</button>
-21
View File
@@ -1,6 +1,4 @@
import { useState, type PointerEvent as ReactPointerEvent } from "react";
import { Bot, PanelRightClose } from "lucide-react";
import { Button, Tooltip } from "antd";
import { motion } from "motion/react";
import { LocalAgentPanel } from "./local-agent-panel";
@@ -18,9 +16,6 @@ export function AgentPanel() {
const panelOpen = useAgentStore((state) => state.panelOpen);
const panelClosing = useAgentStore((state) => state.panelClosing);
const setAgentState = useAgentStore((state) => state.setAgentState);
const closePanel = useAgentStore((state) => state.closePanel);
const startResize = (event: ReactPointerEvent<HTMLButtonElement>) => {
event.preventDefault();
const startX = event.clientX;
@@ -60,22 +55,6 @@ export function AgentPanel() {
style={{ width, background: theme.node.panel, borderColor: theme.node.stroke, color: theme.node.text }}
>
<button type="button" className="absolute inset-y-0 left-0 z-40 w-4 -translate-x-1/2 cursor-col-resize" onPointerDown={startResize} aria-label="调整右侧面板宽度" />
<header className="flex h-14 shrink-0 items-center justify-between border-b px-4" style={{ borderColor: theme.node.stroke }}>
<div className="flex min-w-0 items-center gap-2">
<span className="grid size-8 place-items-center rounded-lg">
<Bot className="size-4" />
</span>
<div className="min-w-0">
<div className="text-base font-semibold leading-5">Agent</div>
<div className="truncate text-xs" style={{ color: theme.node.muted }}></div>
</div>
</div>
<div className="flex shrink-0 items-center gap-2">
<Tooltip title="收起对话">
<Button type="text" shape="circle" className="!h-8 !w-8 !min-w-8" style={{ color: theme.node.muted }} icon={<PanelRightClose className="size-4" />} onClick={closePanel} />
</Tooltip>
</div>
</header>
<LocalAgentPanel embedded />
</motion.aside>
</motion.div>
+14 -2
View File
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useRef } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { App, Button } from "antd";
import { History, MessageSquare, PlugZap, Plus, Terminal } from "lucide-react";
import { App, Button, Tooltip } from "antd";
import { Bot, History, MessageSquare, PanelRightClose, PlugZap, Plus, Terminal } from "lucide-react";
import { canvasThemes } from "@/lib/canvas-theme";
import { imageMetadata } from "@/lib/canvas/canvas-node-factory";
@@ -105,6 +105,7 @@ export function LocalAgentPanel({ embedded, headless, autoConnect }: { embedded?
})),
);
const setAgentState = useAgentStore((state) => state.setAgentState);
const closePanel = useAgentStore((state) => state.closePanel);
const pushMessage = useAgentStore((state) => state.addMessage);
const pushEventLog = useAgentStore((state) => state.addEventLog);
const clearEventLogs = useAgentStore((state) => state.clearEventLogs);
@@ -783,6 +784,14 @@ export function LocalAgentPanel({ embedded, headless, autoConnect }: { embedded?
<AgentPanelTabs
value={activeTab}
theme={theme}
leading={
<div className="flex items-center gap-2 pr-1">
<span className="grid size-8 place-items-center">
<Bot className="size-4" />
</span>
<div className="text-base font-semibold leading-5">Agent</div>
</div>
}
items={[
{ value: "setup", label: "连接", icon: <PlugZap className="size-3.5" /> },
{ value: "chat", label: "对话", icon: <MessageSquare className="size-3.5" /> },
@@ -798,6 +807,9 @@ export function LocalAgentPanel({ embedded, headless, autoConnect }: { embedded?
<Button size="small" type="text" disabled={!connected || loadingThreads || sending || waiting} icon={<Plus className="size-3.5" />} onClick={startNewThread}>
</Button>
<Tooltip title="收起对话">
<Button type="text" shape="circle" className="!h-8 !w-8 !min-w-8" style={{ color: theme.node.muted }} icon={<PanelRightClose className="size-4" />} onClick={closePanel} />
</Tooltip>
</>
}
/>