11// This is a temporary chatbot component that is used to test the chatbot functionality.
22// LlamaIndex will replace it with better chatbot component.
33import { useChatbot } from "@/libs/useChatbot" ;
4- import {
5- Button ,
6- cn ,
7- ScrollArea ,
8- Textarea ,
9- } from "@llamaindex/ui" ;
10- import {
11- Bot ,
12- Loader2 ,
13- RefreshCw ,
14- Send ,
15- User ,
16- } from "lucide-react" ;
4+ import { Button , cn , ScrollArea , Textarea } from "@llamaindex/ui" ;
5+ import { Bot , Loader2 , RefreshCw , Send , User } from "lucide-react" ;
176import { FormEvent , KeyboardEvent , useEffect , useRef } from "react" ;
187
198export default function ChatBot ( {
@@ -48,7 +37,7 @@ export default function ChatBot({
4837 // Reset textarea height when input is cleared
4938 useEffect ( ( ) => {
5039 if ( ! chatbot . input && inputRef . current ) {
51- inputRef . current . style . height = ' 48px' ; // Reset to initial height
40+ inputRef . current . style . height = " 48px" ; // Reset to initial height
5241 }
5342 } , [ chatbot . input ] ) ;
5443
@@ -67,8 +56,8 @@ export default function ChatBot({
6756 } ;
6857
6958 const adjustTextareaHeight = ( textarea : HTMLTextAreaElement ) => {
70- textarea . style . height = ' auto' ;
71- textarea . style . height = Math . min ( textarea . scrollHeight , 128 ) + 'px' ; // 128px = max-h-32
59+ textarea . style . height = " auto" ;
60+ textarea . style . height = Math . min ( textarea . scrollHeight , 128 ) + "px" ; // 128px = max-h-32
7261 } ;
7362
7463 const handleInputChange = ( e : React . ChangeEvent < HTMLTextAreaElement > ) => {
@@ -97,124 +86,127 @@ export default function ChatBot({
9786 { /* Messages */ }
9887 < ScrollArea className = "flex-1 overflow-y-auto" >
9988 < div className = "max-w-4xl mx-auto p-6" >
100- { chatbot . messages . length === 0 ? (
101- < div className = "flex items-center justify-center h-full min-h-[400px]" >
102- < div className = "text-center" >
103- < Bot className = "w-16 h-16 text-muted-foreground/50 mx-auto mb-4" />
104- < p className = "text-lg text-foreground mb-2" >
105- Welcome! 👋 Upload a document with the control above, then ask questions here.
106- </ p >
107- < p className = "text-sm text-muted-foreground" >
108- Start by uploading a document to begin your conversation
109- </ p >
89+ { chatbot . messages . length === 0 ? (
90+ < div className = "flex items-center justify-center h-full min-h-[400px]" >
91+ < div className = "text-center" >
92+ < Bot className = "w-16 h-16 text-muted-foreground/50 mx-auto mb-4" />
93+ < p className = "text-lg text-foreground mb-2" >
94+ Welcome! 👋 Upload a document with the control above, then ask
95+ questions here.
96+ </ p >
97+ < p className = "text-sm text-muted-foreground" >
98+ Start by uploading a document to begin your conversation
99+ </ p >
100+ </ div >
110101 </ div >
111- </ div >
112- ) : (
113- < div className = "space-y-6" >
114- { chatbot . messages . map ( ( message , i ) => (
115- < div
116- key = { i }
117- className = { cn (
118- "flex gap-4" ,
119- message . role === "user" ? "justify-end" : "justify-start" ,
120- ) }
121- >
122- { message . role !== "user" && (
123- < div
124- className = { cn (
125- "w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 mt-1" ,
126- message . error
127- ? "bg-destructive/10 text-destructive"
128- : "bg-primary/10 text-primary" ,
129- ) }
130- >
131- < Bot className = "w-5 h-5" />
132- </ div >
133- ) }
102+ ) : (
103+ < div className = "space-y-6" >
104+ { chatbot . messages . map ( ( message , i ) => (
134105 < div
106+ key = { i }
135107 className = { cn (
136- "max-w-[75%] " ,
137- message . role === "user" ? "order-1 " : "order-2 " ,
108+ "flex gap-4 " ,
109+ message . role === "user" ? "justify-end " : "justify-start " ,
138110 ) }
139111 >
112+ { message . role !== "user" && (
113+ < div
114+ className = { cn (
115+ "w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 mt-1" ,
116+ message . error
117+ ? "bg-destructive/10 text-destructive"
118+ : "bg-primary/10 text-primary" ,
119+ ) }
120+ >
121+ < Bot className = "w-5 h-5" />
122+ </ div >
123+ ) }
140124 < div
141125 className = { cn (
142- "rounded-2xl px-4 py-3" ,
143- message . role === "user"
144- ? "bg-primary text-primary-foreground"
145- : message . error
146- ? "bg-destructive/5 border border-destructive/20"
147- : "bg-muted" ,
126+ "max-w-[75%]" ,
127+ message . role === "user" ? "order-1" : "order-2" ,
148128 ) }
149129 >
150- { message . isPartial && ! message . content ? (
151- < LoadingDots />
152- ) : (
153- < p className = "whitespace-pre-wrap text-sm leading-relaxed" >
154- { message . content }
155- </ p >
156- ) }
157- < p
130+ < div
158131 className = { cn (
159- "text-xs mt-2 opacity-60 " ,
132+ "rounded-2xl px-4 py-3 " ,
160133 message . role === "user"
161- ? "text-primary-foreground"
134+ ? "bg-primary text-primary-foreground"
162135 : message . error
163- ? "text -destructive"
164- : "text -muted-foreground " ,
136+ ? "bg -destructive/5 border border-destructive/20 "
137+ : "bg -muted" ,
165138 ) }
166139 >
167- { message . timestamp . toLocaleTimeString ( ) }
168- </ p >
140+ { message . isPartial && ! message . content ? (
141+ < div className = "m-2" >
142+ < LoadingDots />
143+ </ div >
144+ ) : (
145+ < p className = "whitespace-pre-wrap text-sm leading-relaxed" >
146+ { message . content }
147+ </ p >
148+ ) }
149+ < p
150+ className = { cn (
151+ "text-xs mt-2 opacity-60" ,
152+ message . role === "user"
153+ ? "text-primary-foreground"
154+ : message . error
155+ ? "text-destructive"
156+ : "text-muted-foreground" ,
157+ ) }
158+ >
159+ { message . timestamp . toLocaleTimeString ( ) }
160+ </ p >
161+ </ div >
169162 </ div >
163+ { message . role === "user" && (
164+ < div className = "w-8 h-8 rounded-full bg-muted flex items-center justify-center flex-shrink-0 order-2 mt-1" >
165+ < User className = "w-5 h-5 text-muted-foreground" />
166+ </ div >
167+ ) }
170168 </ div >
171- { message . role === "user" && (
172- < div className = "w-8 h-8 rounded-full bg-muted flex items-center justify-center flex-shrink-0 order-2 mt-1" >
173- < User className = "w-5 h-5 text-muted-foreground" />
174- </ div >
175- ) }
176- </ div >
177- ) ) }
178- < div ref = { messagesEndRef } />
179- </ div >
180- ) }
169+ ) ) }
170+ < div ref = { messagesEndRef } />
171+ </ div >
172+ ) }
181173 </ div >
182174 </ ScrollArea >
183175
184176 { /* Input */ }
185177 < div className = "border-t bg-background" >
186178 < div className = "max-w-4xl mx-auto p-6" >
187- < form onSubmit = { handleSubmit } className = "flex gap-3" >
188- < Textarea
189- ref = { inputRef }
190- value = { chatbot . input }
191- onChange = { handleInputChange }
192- onKeyDown = { handleKeyDown }
193- placeholder = { placeholder }
194- disabled = { chatbot . isLoading }
195- className = "flex-1 min-h-12 max-h-32 rounded-xl border-2 focus:border-primary resize-none overflow-hidden"
196- autoFocus
197- style = { { height : ' 48px' } } // Initial height (min-h-12)
198- />
199- < Button
200- type = "submit"
201- disabled = {
202- ! chatbot . canSend || chatbot . isLoading || ! chatbot . input . trim ( )
203- }
204- size = "icon"
205- title = "Send message"
206- className = "h-12 w-12 rounded-xl"
207- >
208- { ! chatbot . canSend || chatbot . isLoading ? (
209- < Loader2 className = "w-5 h-5 animate-spin" />
210- ) : (
211- < Send className = "w-5 h-5" />
212- ) }
213- </ Button >
214- </ form >
215- < p className = "text-xs text-muted-foreground mt-3 text-center" >
216- Press Enter to send • Shift+Enter for new line
217- </ p >
179+ < form onSubmit = { handleSubmit } className = "flex gap-3" >
180+ < Textarea
181+ ref = { inputRef }
182+ value = { chatbot . input }
183+ onChange = { handleInputChange }
184+ onKeyDown = { handleKeyDown }
185+ placeholder = { placeholder }
186+ disabled = { chatbot . isLoading }
187+ className = "flex-1 min-h-12 max-h-32 rounded-xl border-2 focus:border-primary resize-none overflow-hidden"
188+ autoFocus
189+ style = { { height : " 48px" } } // Initial height (min-h-12)
190+ />
191+ < Button
192+ type = "submit"
193+ disabled = {
194+ ! chatbot . canSend || chatbot . isLoading || ! chatbot . input . trim ( )
195+ }
196+ size = "icon"
197+ title = "Send message"
198+ className = "h-12 w-12 rounded-xl"
199+ >
200+ { ! chatbot . canSend || chatbot . isLoading ? (
201+ < Loader2 className = "w-5 h-5 animate-spin" />
202+ ) : (
203+ < Send className = "w-5 h-5" />
204+ ) }
205+ </ Button >
206+ </ form >
207+ < p className = "text-xs text-muted-foreground mt-3 text-center" >
208+ Press Enter to send • Shift+Enter for new line
209+ </ p >
218210 </ div >
219211 </ div >
220212 </ div >
0 commit comments