@@ -4,6 +4,7 @@ import "@copilotkit/react-ui/styles.css";
44import "./style.css" ;
55import { CopilotKit , useCoAgentStateRender } from "@copilotkit/react-core" ;
66import { CopilotChat } from "@copilotkit/react-ui" ;
7+ import { useTheme } from "next-themes" ;
78
89interface AgenticGenerativeUIProps {
910 params : Promise < {
@@ -33,42 +34,146 @@ interface AgentState {
3334}
3435
3536const Chat = ( ) => {
37+ const { theme } = useTheme ( ) ;
3638 useCoAgentStateRender < AgentState > ( {
3739 name : "agentic_generative_ui" ,
3840 render : ( { state } ) => {
3941 if ( ! state . steps || state . steps . length === 0 ) {
4042 return null ;
4143 }
4244
45+ const completedCount = state . steps . filter ( step => step . status === "completed" ) . length ;
46+ const progressPercentage = ( completedCount / state . steps . length ) * 100 ;
47+
4348 return (
4449 < div className = "flex" >
45- < div className = "bg-gray-100 rounded-lg w-[800px] p-4 text-black space-y-2" >
46- { state . steps . map ( ( step , index ) => {
47- if ( step . status === "completed" ) {
48- return (
49- < div key = { index } className = "text-sm" >
50- ✓ { step . description }
51- </ div >
52- ) ;
53- } else if (
54- step . status === "pending" &&
55- index === state . steps . findIndex ( ( s ) => s . status === "pending" )
56- ) {
57- return (
58- < div key = { index } className = "text-2xl font-bold text-slate-700" >
59- < Spinner />
60- { step . description }
61- </ div >
62- ) ;
63- } else {
50+ < div className = { `relative rounded-xl w-[700px] p-6 shadow-lg backdrop-blur-sm ${
51+ theme === "dark"
52+ ? "bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-white border border-slate-700/50 shadow-2xl"
53+ : "bg-gradient-to-br from-white via-gray-50 to-white text-gray-800 border border-gray-200/80"
54+ } `} >
55+ { /* Header */ }
56+ < div className = "mb-5" >
57+ < div className = "flex items-center justify-between mb-3" >
58+ < h3 className = "text-xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent" >
59+ Task Progress
60+ </ h3 >
61+ < div className = { `text-sm ${ theme === "dark" ? "text-slate-400" : "text-gray-500" } ` } >
62+ { completedCount } /{ state . steps . length } Complete
63+ </ div >
64+ </ div >
65+
66+ { /* Progress Bar */ }
67+ < div className = { `relative h-2 rounded-full overflow-hidden ${ theme === "dark" ? "bg-slate-700" : "bg-gray-200" } ` } >
68+ < div
69+ className = "absolute top-0 left-0 h-full bg-gradient-to-r from-blue-500 to-purple-500 rounded-full transition-all duration-1000 ease-out"
70+ style = { { width : `${ progressPercentage } %` } }
71+ />
72+ < div className = { `absolute top-0 left-0 h-full w-full bg-gradient-to-r from-transparent to-transparent animate-pulse ${
73+ theme === "dark" ? "via-white/20" : "via-white/40"
74+ } `} />
75+ </ div >
76+ </ div >
77+
78+ { /* Steps */ }
79+ < div className = "space-y-2" >
80+ { state . steps . map ( ( step , index ) => {
81+ const isCompleted = step . status === "completed" ;
82+ const isCurrentPending = step . status === "pending" &&
83+ index === state . steps . findIndex ( ( s ) => s . status === "pending" ) ;
84+ const isFuturePending = step . status === "pending" && ! isCurrentPending ;
85+
6486 return (
65- < div key = { index } className = "text-sm" >
66- < Spinner />
67- { step . description }
87+ < div
88+ key = { index }
89+ className = { `relative flex items-center p-2.5 rounded-lg transition-all duration-500 ${
90+ isCompleted
91+ ? theme === "dark"
92+ ? "bg-gradient-to-r from-green-900/30 to-emerald-900/20 border border-green-500/30"
93+ : "bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200/60"
94+ : isCurrentPending
95+ ? theme === "dark"
96+ ? "bg-gradient-to-r from-blue-900/40 to-purple-900/30 border border-blue-500/50 shadow-lg shadow-blue-500/20"
97+ : "bg-gradient-to-r from-blue-50 to-purple-50 border border-blue-200/60 shadow-md shadow-blue-200/50"
98+ : theme === "dark"
99+ ? "bg-slate-800/50 border border-slate-600/30"
100+ : "bg-gray-50/50 border border-gray-200/60"
101+ } `}
102+ >
103+ { /* Connector Line */ }
104+ { index < state . steps . length - 1 && (
105+ < div className = { `absolute left-5 top-full w-0.5 h-2 bg-gradient-to-b ${
106+ theme === "dark" ? "from-slate-500 to-slate-600" : "from-gray-300 to-gray-400"
107+ } `} />
108+ ) }
109+
110+ { /* Status Icon */ }
111+ < div className = { `flex-shrink-0 w-6 h-6 rounded-full flex items-center justify-center mr-2 ${
112+ isCompleted
113+ ? theme === "dark"
114+ ? "bg-gradient-to-br from-green-500 to-emerald-600 shadow-lg shadow-green-500/30"
115+ : "bg-gradient-to-br from-green-500 to-emerald-600 shadow-md shadow-green-200"
116+ : isCurrentPending
117+ ? theme === "dark"
118+ ? "bg-gradient-to-br from-blue-500 to-purple-600 shadow-lg shadow-blue-500/30"
119+ : "bg-gradient-to-br from-blue-500 to-purple-600 shadow-md shadow-blue-200"
120+ : theme === "dark"
121+ ? "bg-slate-700 border border-slate-600"
122+ : "bg-gray-300 border border-gray-400"
123+ } `} >
124+ { isCompleted ? (
125+ < CheckIcon />
126+ ) : isCurrentPending ? (
127+ < SpinnerIcon />
128+ ) : (
129+ < ClockIcon theme = { theme } />
130+ ) }
131+ </ div >
132+
133+ { /* Step Content */ }
134+ < div className = "flex-1 min-w-0" >
135+ < div className = { `font-semibold transition-all duration-300 text-sm ${
136+ isCompleted
137+ ? theme === "dark" ? "text-green-300" : "text-green-700"
138+ : isCurrentPending
139+ ? theme === "dark" ? "text-blue-300 text-base" : "text-blue-700 text-base"
140+ : theme === "dark" ? "text-slate-400" : "text-gray-500"
141+ } `} >
142+ { step . description }
143+ </ div >
144+ { isCurrentPending && (
145+ < div className = { `text-sm mt-1 animate-pulse ${
146+ theme === "dark" ? "text-blue-400" : "text-blue-600"
147+ } `} >
148+ Processing...
149+ </ div >
150+ ) }
151+ </ div >
152+
153+ { /* Animated Background for Current Step */ }
154+ { isCurrentPending && (
155+ < div className = { `absolute inset-0 rounded-lg bg-gradient-to-r animate-pulse ${
156+ theme === "dark"
157+ ? "from-blue-500/10 to-purple-500/10"
158+ : "from-blue-100/50 to-purple-100/50"
159+ } `} />
160+ ) }
68161 </ div >
69162 ) ;
70- }
71- } ) }
163+ } ) }
164+ </ div >
165+
166+ { /* Decorative Elements */ }
167+ < div className = { `absolute top-3 right-3 w-16 h-16 rounded-full blur-xl ${
168+ theme === "dark"
169+ ? "bg-gradient-to-br from-blue-500/10 to-purple-500/10"
170+ : "bg-gradient-to-br from-blue-200/30 to-purple-200/30"
171+ } `} />
172+ < div className = { `absolute bottom-3 left-3 w-12 h-12 rounded-full blur-xl ${
173+ theme === "dark"
174+ ? "bg-gradient-to-br from-green-500/10 to-emerald-500/10"
175+ : "bg-gradient-to-br from-green-200/30 to-emerald-200/30"
176+ } `} />
72177 </ div >
73178 </ div >
74179 ) ;
@@ -90,10 +195,19 @@ const Chat = () => {
90195 ) ;
91196} ;
92197
93- function Spinner ( ) {
198+ // Enhanced Icons
199+ function CheckIcon ( ) {
200+ return (
201+ < svg className = "w-4 h-4 text-white" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
202+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 3 } d = "M5 13l4 4L19 7" />
203+ </ svg >
204+ ) ;
205+ }
206+
207+ function SpinnerIcon ( ) {
94208 return (
95209 < svg
96- className = "mr-2 size-3 animate-spin text-slate-500 "
210+ className = "w-4 h-4 animate-spin text-white "
97211 xmlns = "http://www.w3.org/2000/svg"
98212 fill = "none"
99213 viewBox = "0 0 24 24"
@@ -105,12 +219,21 @@ function Spinner() {
105219 r = "10"
106220 stroke = "currentColor"
107221 strokeWidth = "4"
108- > </ circle >
222+ / >
109223 < path
110224 className = "opacity-75"
111225 fill = "currentColor"
112226 d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
113- > </ path >
227+ />
228+ </ svg >
229+ ) ;
230+ }
231+
232+ function ClockIcon ( { theme } : { theme ?: string } ) {
233+ return (
234+ < svg className = { `w-3 h-3 ${ theme === "dark" ? "text-slate-400" : "text-gray-600" } ` } fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
235+ < circle cx = "12" cy = "12" r = "10" strokeWidth = "2" />
236+ < polyline points = "12,6 12,12 16,14" strokeWidth = "2" />
114237 </ svg >
115238 ) ;
116239}
0 commit comments