@@ -14,8 +14,19 @@ import {
1414import { useAtom } from 'jotai' ;
1515import { useEffect , useRef , useState } from 'react' ;
1616import { Button } from '@/components/ui/button' ;
17- import { Input } from '@/components/ui/input' ;
1817import { Skeleton } from '@/components/ui/skeleton' ;
18+ import {
19+ PromptInput ,
20+ PromptInputTextarea ,
21+ PromptInputSubmit ,
22+ PromptInputToolbar ,
23+ } from '@/components/ai-elements/prompt-input' ;
24+ import {
25+ Conversation ,
26+ ConversationContent ,
27+ ConversationScrollButton ,
28+ } from '@/components/ai-elements/conversation' ;
29+ import { Suggestions , Suggestion } from '@/components/ai-elements/suggestion' ;
1930import { cn } from '@/lib/utils' ;
2031import {
2132 inputValueAtom ,
@@ -81,7 +92,7 @@ export default function ChatSection() {
8192 const [ selectedModel ] = useAtom ( modelAtom ) ;
8293 const [ websiteData ] = useAtom ( websiteDataAtom ) ;
8394
84- const inputRef = useRef < HTMLInputElement > ( null ) ;
95+ const inputRef = useRef < HTMLTextAreaElement > ( null ) ;
8596 const bottomRef = useRef < HTMLDivElement > ( null ) ;
8697 const { sendMessage, handleKeyPress, scrollToBottom, resetChat } = useChat ( ) ;
8798 const [ showChatHistory , setShowChatHistory ] = useState ( false ) ;
@@ -201,12 +212,9 @@ export default function ChatSection() {
201212 </ div >
202213
203214 { /* Messages Area */ }
204- < div
205- className = "min-h-0 flex-1 overflow-y-auto overscroll-contain"
206- ref = { scrollAreaRef }
207- >
208- { /* Welcome State */ }
209- < div className = "min-h-full px-4 py-3" >
215+ < Conversation className = "min-h-0 flex-1" >
216+ < ConversationContent className = "min-h-full" >
217+ < ConversationScrollButton />
210218 { ! ( hasMessages || isLoading ) && (
211219 < div className = "fade-in-0 slide-in-from-bottom-4 h-full animate-in space-y-6 duration-500" >
212220 < div className = "flex h-full flex-col justify-between" >
@@ -232,37 +240,24 @@ export default function ChatSection() {
232240 < LightningIcon className = "h-4 w-4" weight = "duotone" />
233241 < span > Try these examples:</ span >
234242 </ div >
235- < div className = "grid grid-cols-1 gap-2 md:grid-cols-2" >
236- { quickQuestions . map ( ( question , index ) => (
237- < Button
238- className = { cn (
239- 'h-auto px-4 py-3 text-left font-normal text-sm' ,
240- 'hover:bg-gradient-to-r hover:from-primary/5 hover:to-accent/5' ,
241- 'border-dashed transition-all duration-300 hover:border-solid' ,
242- 'fade-in-0 slide-in-from-left-2 animate-in'
243- ) }
244- disabled = { isLoading || isRateLimited }
243+ < Suggestions >
244+ { quickQuestions . map ( ( question ) => (
245+ < Suggestion
245246 key = { question . text }
246- onClick = { ( ) => {
247+ suggestion = { question . text }
248+ disabled = { isLoading || isRateLimited }
249+ onClick = { ( suggestion ) => {
247250 if ( ! ( isLoading || isRateLimited ) ) {
248- sendMessage ( question . text ) ;
251+ sendMessage ( suggestion ) ;
249252 scrollToBottom ( ) ;
250253 }
251254 } }
252- size = "sm"
253- style = { { animationDelay : `${ index * 100 } ms` } }
254- variant = "outline"
255255 >
256- < question . icon className = "mr-3 h-4 w-4 flex-shrink-0 text-primary/70" />
257- < div className = "flex-1" >
258- < div className = "font-medium" > { question . text } </ div >
259- < div className = "text-muted-foreground text-xs capitalize" >
260- { question . type } response
261- </ div >
262- </ div >
263- </ Button >
256+ < question . icon className = "mr-2 h-4 w-4 text-primary/70" />
257+ { question . text }
258+ </ Suggestion >
264259 ) ) }
265- </ div >
260+ </ Suggestions >
266261 </ div >
267262 </ div >
268263 </ div >
@@ -274,33 +269,23 @@ export default function ChatSection() {
274269 { messages . map ( ( message ) => (
275270 < MessageBubble key = { message . id } message = { message } />
276271 ) ) }
277- < div ref = { bottomRef } />
278272 </ div >
279273 ) }
280- </ div >
281- </ div >
274+ </ ConversationContent >
275+ </ Conversation >
282276
283277 { /* Enhanced Input Area */ }
284278 < div className = "flex-shrink-0 border-t bg-gradient-to-r from-muted/10 to-muted/5 p-4" >
285279 < div className = "relative" >
286- < div className = { cn ( 'flex gap-3' ) } >
287- < Input
288- className = { cn (
289- 'h-11 flex-1 rounded-xl border-2 bg-background/50 backdrop-blur-sm' ,
290- 'placeholder:text-muted-foreground/60' ,
291- 'focus:border-primary/30 focus:bg-background/80' ,
292- 'transition-all duration-200'
293- ) }
280+ < PromptInput
281+ onSubmit = { ( e ) => {
282+ e . preventDefault ( ) ;
283+ handleSend ( ) ;
284+ } }
285+ >
286+ < PromptInputTextarea
294287 disabled = { isLoading || isRateLimited }
295288 onChange = { ( e ) => setInputValue ( e . target . value ) }
296- onKeyDown = { ( e ) => {
297- if ( e . key === 'Enter' && ! e . shiftKey ) {
298- e . preventDefault ( ) ;
299- handleSend ( ) ;
300- } else {
301- handleKeyPress ( e ) ;
302- }
303- } }
304289 placeholder = {
305290 isLoading
306291 ? 'Databunny is thinking...'
@@ -310,34 +295,17 @@ export default function ChatSection() {
310295 }
311296 ref = { inputRef }
312297 value = { inputValue }
298+ minHeight = { 44 }
299+ maxHeight = { 120 }
313300 />
314- < Button
315- className = { cn (
316- 'h-11 w-11 flex-shrink-0 rounded-xl' ,
317- 'bg-gradient-to-r from-primary to-primary/80' ,
318- 'hover:from-primary/90 hover:to-primary/70' ,
319- 'shadow-lg transition-all duration-200' ,
320- ( ! inputValue . trim ( ) || isRateLimited ) &&
321- ! isLoading &&
322- 'opacity-50'
323- ) }
324- disabled = { ! inputValue . trim ( ) || isLoading || isRateLimited }
325- onClick = { handleSend }
326- size = "icon"
327- title = "Send message"
328- >
329- < PaperPlaneRightIcon
330- className = { cn (
331- 'h-4 w-4' ,
332- inputValue . trim ( ) &&
333- ! isLoading &&
334- ! isRateLimited &&
335- 'scale-110'
336- ) }
337- weight = "duotone"
301+ < PromptInputToolbar >
302+ < div />
303+ < PromptInputSubmit
304+ disabled = { ! inputValue . trim ( ) || isLoading || isRateLimited }
305+ status = { isLoading ? 'submitted' : undefined }
338306 />
339- </ Button >
340- </ div >
307+ </ PromptInputToolbar >
308+ </ PromptInput >
341309
342310 { /* Helper text */ }
343311 < div className = "mt-3 flex flex-wrap items-center justify-between gap-2 text-xs" >
0 commit comments