fix: stabilize agent UI and SCADA card
This commit is contained in:
@@ -16,6 +16,7 @@ import { useState, type ReactNode } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import {
|
||||
agentEase,
|
||||
agentLayoutTransition,
|
||||
agentPanelItemVariants,
|
||||
agentPanelListVariants,
|
||||
@@ -117,20 +118,20 @@ export function AgentMessageDetails({
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div className="space-y-2" layout variants={agentPanelListVariants} animate="animate">
|
||||
<motion.div className="space-y-2" variants={agentPanelListVariants} animate="animate">
|
||||
<AnimatePresence initial={false} mode="popLayout">
|
||||
{message.todos ? (
|
||||
<motion.div key="todos" layout initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<motion.div key="todos" initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<TodoCard todoUpdate={message.todos} />
|
||||
</motion.div>
|
||||
) : null}
|
||||
{message.permissions?.length ? (
|
||||
<motion.div key="permissions" layout initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<motion.div key="permissions" initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<PermissionList permissions={message.permissions} onReplyPermission={onReplyPermission} />
|
||||
</motion.div>
|
||||
) : null}
|
||||
{message.questions?.length ? (
|
||||
<motion.div key="questions" layout initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<motion.div key="questions" initial="initial" animate="animate" exit="exit" variants={agentPanelItemVariants}>
|
||||
<QuestionList
|
||||
questions={message.questions}
|
||||
onReplyQuestion={onReplyQuestion}
|
||||
@@ -184,7 +185,6 @@ function AgentNestedBlock({
|
||||
function AnimatedDetailItem({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
@@ -198,8 +198,8 @@ function AnimatedDetailItem({ children }: { children: ReactNode }) {
|
||||
|
||||
function ProgressList({ progress, running }: { progress: AgentChatProgress[]; running: boolean }) {
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const recentProgress = progress.slice(-3);
|
||||
const visibleProgress = expanded ? progress : running ? recentProgress : [];
|
||||
const visibleProgress = expanded ? progress : progress.slice(-1);
|
||||
const listMode = expanded ? "expanded" : "summary";
|
||||
|
||||
return (
|
||||
<div className="agent-panel-nested rounded-xl p-2.5">
|
||||
@@ -216,7 +216,7 @@ function ProgressList({ progress, running }: { progress: AgentChatProgress[]; ru
|
||||
{expanded
|
||||
? `全部 ${progress.length} 条`
|
||||
: running
|
||||
? `最近 ${recentProgress.length} 条`
|
||||
? "当前步骤"
|
||||
: `共 ${progress.length} 条`}
|
||||
</span>
|
||||
<ChevronDown
|
||||
@@ -225,43 +225,68 @@ function ProgressList({ progress, running }: { progress: AgentChatProgress[]; ru
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<AnimatePresence initial={false}>
|
||||
<AnimatePresence initial={false} mode="wait">
|
||||
{visibleProgress.length ? (
|
||||
<motion.ol
|
||||
key={listMode}
|
||||
aria-label={expanded ? "全部执行进度" : "当前执行进度"}
|
||||
className="mt-2 space-y-1.5 overflow-hidden"
|
||||
initial={{ height: 0, opacity: 0 }}
|
||||
animate={{ height: "auto", opacity: 1 }}
|
||||
exit={{ height: 0, opacity: 0 }}
|
||||
transition={agentLayoutTransition}
|
||||
>
|
||||
{visibleProgress.map((item) => (
|
||||
<li key={item.id} className="grid grid-cols-[16px_1fr_auto] items-start gap-2 text-xs">
|
||||
<span
|
||||
className={cn(
|
||||
"mt-0.5 h-3.5 w-3.5 rounded-full border",
|
||||
progressStatusMeta[item.status].dotClassName
|
||||
)}
|
||||
/>
|
||||
<span className="min-w-0">
|
||||
<span className="block truncate font-semibold text-slate-800" title={item.title}>
|
||||
{item.title}
|
||||
</span>
|
||||
{item.detail ? (
|
||||
<span className="block line-clamp-2 whitespace-pre-wrap leading-5 text-slate-500">
|
||||
{item.detail}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-full px-2 py-0.5 font-semibold",
|
||||
progressStatusMeta[item.status].className
|
||||
)}
|
||||
<AnimatePresence initial={false} mode={expanded ? "sync" : "wait"}>
|
||||
{visibleProgress.map((item) => (
|
||||
<motion.li
|
||||
key={item.id}
|
||||
className="grid min-h-7 grid-cols-[16px_1fr_auto] items-start gap-2 text-xs"
|
||||
initial={{ opacity: 0, y: 4 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -2 }}
|
||||
transition={{ duration: 0.16, ease: agentEase }}
|
||||
>
|
||||
{progressStatusMeta[item.status].label}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
<motion.span
|
||||
aria-hidden="true"
|
||||
className={cn(
|
||||
"mt-0.5 h-3.5 w-3.5 rounded-full border transition-colors duration-150",
|
||||
progressStatusMeta[item.status].dotClassName
|
||||
)}
|
||||
animate={item.status === "running" ? { opacity: [0.45, 1, 0.45] } : { opacity: 1 }}
|
||||
transition={
|
||||
item.status === "running"
|
||||
? { duration: 1.2, ease: "easeInOut", repeat: Infinity }
|
||||
: { duration: 0.14 }
|
||||
}
|
||||
/>
|
||||
<span className="min-w-0">
|
||||
<span className="block truncate font-semibold text-slate-800" title={item.title}>
|
||||
{item.title}
|
||||
</span>
|
||||
{item.detail ? (
|
||||
<span className="block line-clamp-2 whitespace-pre-wrap leading-5 text-slate-500">
|
||||
{item.detail}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
<AnimatePresence initial={false} mode="wait">
|
||||
<motion.span
|
||||
key={item.status}
|
||||
className={cn(
|
||||
"min-w-12 rounded-full px-2 py-0.5 text-center font-semibold",
|
||||
progressStatusMeta[item.status].className
|
||||
)}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.14 }}
|
||||
>
|
||||
{progressStatusMeta[item.status].label}
|
||||
</motion.span>
|
||||
</AnimatePresence>
|
||||
</motion.li>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</motion.ol>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
@@ -277,7 +302,6 @@ function TodoCard({ todoUpdate }: { todoUpdate: AgentTodoUpdate }) {
|
||||
{todoUpdate.todos.slice(0, 6).map((todo) => (
|
||||
<motion.li
|
||||
key={todo.id}
|
||||
layout
|
||||
className="grid grid-cols-[16px_1fr_auto] items-start gap-2 text-xs"
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
|
||||
Reference in New Issue
Block a user