98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { Plus, Search, Sparkles, Wand2 } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface AgentPanelHeaderProps {
|
|
title?: string;
|
|
description?: string;
|
|
searchValue: string;
|
|
onSearchChange: (value: string) => void;
|
|
searchPlaceholder?: string;
|
|
onCreateClick?: () => void;
|
|
createLabel?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function AgentPanelHeader({
|
|
title = "智能体",
|
|
description = "选择模式后,工作台会自动加载对应槽位和生成能力",
|
|
searchValue,
|
|
onSearchChange,
|
|
searchPlaceholder = "搜索智能体...",
|
|
onCreateClick,
|
|
createLabel = "新建智能体",
|
|
className,
|
|
}: AgentPanelHeaderProps) {
|
|
return (
|
|
<div className={cn("border-b border-slate-200/60 bg-white/50 p-5 dark:border-slate-800/60 dark:bg-slate-950/50", className)}>
|
|
{/* 标题区域 */}
|
|
<div className="mb-4 flex items-start justify-between gap-4">
|
|
<div>
|
|
<motion.div
|
|
className="flex items-center gap-2"
|
|
initial={{ opacity: 0, x: -10 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
>
|
|
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-500 to-violet-600 text-white shadow-lg shadow-indigo-500/20">
|
|
<Wand2 className="h-4 w-4" />
|
|
</div>
|
|
<h2 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
|
|
{title}
|
|
</h2>
|
|
</motion.div>
|
|
<motion.p
|
|
className="mt-1.5 text-xs leading-relaxed text-slate-500 dark:text-slate-400"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
transition={{ duration: 0.3, delay: 0.1 }}
|
|
>
|
|
{description}
|
|
</motion.p>
|
|
</div>
|
|
{onCreateClick && (
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
transition={{ duration: 0.3, delay: 0.15 }}
|
|
>
|
|
<Button
|
|
size="sm"
|
|
onClick={onCreateClick}
|
|
className="h-9 gap-1.5 rounded-xl bg-slate-900 px-4 text-xs font-medium text-white shadow-md shadow-slate-900/10 transition-all hover:bg-slate-800 hover:shadow-lg hover:shadow-slate-900/20 dark:bg-indigo-600 dark:hover:bg-indigo-500"
|
|
>
|
|
<Plus className="h-3.5 w-3.5" />
|
|
{createLabel}
|
|
</Button>
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
|
|
{/* 搜索框 */}
|
|
<motion.div
|
|
className="relative"
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.2 }}
|
|
>
|
|
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
|
|
<Input
|
|
placeholder={searchPlaceholder}
|
|
value={searchValue}
|
|
onChange={(event) => onSearchChange(event.target.value)}
|
|
className={cn(
|
|
"h-10 rounded-xl border-slate-200/60 bg-white pl-10 text-sm",
|
|
"placeholder:text-slate-400",
|
|
"focus:border-indigo-500/50 focus:ring-indigo-500/20",
|
|
"dark:border-slate-800/60 dark:bg-slate-900/50"
|
|
)}
|
|
/>
|
|
</motion.div>
|
|
</div>
|
|
);
|
|
}
|