1+
12"use client" ;
23
4+ import { useEffect , useState } from "react" ;
35import { Attachment , Message } from "ai" ;
46import { useChat } from "ai/react" ;
5- import { useState } from "react" ;
67
78import { Message as PreviewMessage } from "@/components/custom/message" ;
89import { useScrollToBottom } from "@/components/custom/use-scroll-to-bottom" ;
@@ -28,73 +29,123 @@ export function Chat({
2829 } ,
2930 } ) ;
3031
31- const [ messagesContainerRef , messagesEndRef ] =
32- useScrollToBottom < HTMLDivElement > ( ) ;
33-
32+ const [ messagesContainerRef , messagesEndRef ] = useScrollToBottom < HTMLDivElement > ( ) ;
3433 const [ attachments , setAttachments ] = useState < Array < Attachment > > ( [ ] ) ;
3534
35+ // Show initial state if no messages (except system/assistant)
36+ const hasUserMessages = messages . some ( m => m . role === "user" || m . role === "assistant" ) ;
37+
38+ // Scroll to bottom on new message or loading
39+ useEffect ( ( ) => {
40+ if ( messagesEndRef && messagesEndRef . current ) {
41+ messagesEndRef . current . scrollIntoView ( { behavior : "smooth" } ) ;
42+ }
43+ } , [ messages . length , isLoading ] ) ;
44+
3645 return (
37- < div className = "flex flex-row justify-center pb-4 md:pb-8 h-dvh bg-background" >
38- < div className = "flex flex-col justify-between items-center gap-4" >
39- { /* Italian train route suggestions */ }
40- < div className = "flex flex-row gap-4 mb-4" >
41- < button
42- className = "bg-muted px-4 py-2 rounded-lg text-left text-muted-foreground hover:bg-zinc-800"
43- onClick = { ( ) => append ( {
44- role : "user" ,
45- content : "Book a train from Rome to Florence" ,
46- } ) }
47- >
48- < div className = "font-medium" > Book a train from Rome to Florence</ div >
49- < div className = "text-xs" > from Roma Termini to Firenze SMN</ div >
50- </ button >
51- < button
52- className = "bg-muted px-4 py-2 rounded-lg text-left text-muted-foreground hover:bg-zinc-800"
53- onClick = { ( ) => append ( {
54- role : "user" ,
55- content : "What is the status of train ITALO9512 departing tomorrow?" ,
56- } ) }
57- >
58- < div className = "font-medium" > What is the status</ div >
59- < div className = "text-xs" > of train ITALO9512 departing tomorrow?</ div >
60- </ button >
46+ < div className = "flex flex-col items-center justify-center h-dvh w-dvw bg-background" >
47+ < style > { `
48+ .custom-scrollbar {
49+ scrollbar-width: thin;
50+ scrollbar-color: transparent transparent;
51+ }
52+ .custom-scrollbar:hover, .custom-scrollbar:active, .custom-scrollbar:focus, .custom-scrollbar:scroll {
53+ scrollbar-color: rgba(255,255,255,0.2) transparent;
54+ }
55+ .custom-scrollbar::-webkit-scrollbar {
56+ width: 8px;
57+ background: transparent;
58+ }
59+ .custom-scrollbar:hover::-webkit-scrollbar-thumb {
60+ background: rgba(255,255,255,0.2);
61+ border-radius: 4px;
62+ }
63+ .custom-scrollbar::-webkit-scrollbar-thumb {
64+ background: transparent;
65+ }
66+ ` } </ style >
67+ { ! hasUserMessages ? (
68+ // Initial state: centered input and logo
69+ < div className = "flex flex-col items-center justify-center h-full w-full" >
70+ { /* Updated Rail logo */ }
71+ < img src = "/images/ir-logo.png" alt = "Rail Logo" className = "w-20 h-20 mb-6 rounded-full shadow object-cover" />
72+ < form className = "flex flex-row gap-3 items-center w-full max-w-xl px-6" >
73+ < MultimodalInput
74+ input = { input }
75+ setInput = { setInput }
76+ handleSubmit = { handleSubmit }
77+ isLoading = { isLoading }
78+ stop = { stop }
79+ attachments = { attachments }
80+ setAttachments = { setAttachments }
81+ messages = { messages }
82+ append = { append }
83+ />
84+ </ form >
6185 </ div >
86+ ) : (
87+ // Chat state: messages and input at bottom
88+ < div className = "flex flex-col justify-between items-center gap-6 h-full w-full" >
89+ { /* Italian train route suggestions */ }
90+ < div className = "flex flex-row gap-6 mb-6" >
91+ < button
92+ className = "bg-muted px-6 py-4 rounded-xl text-left text-lg text-muted-foreground hover:bg-zinc-800"
93+ onClick = { ( ) => append ( {
94+ role : "user" ,
95+ content : "Book a train from Rome to Florence" ,
96+ } ) }
97+ >
98+ < div className = "font-medium" > Book a train from Rome to Florence</ div >
99+ < div className = "text-xs" > from Roma Termini to Firenze SMN</ div >
100+ </ button >
101+ < button
102+ className = "bg-muted px-6 py-4 rounded-xl text-left text-lg text-muted-foreground hover:bg-zinc-800"
103+ onClick = { ( ) => append ( {
104+ role : "user" ,
105+ content : "What is the status of train ITALO9512 departing tomorrow?" ,
106+ } ) }
107+ >
108+ < div className = "font-medium" > What is the status</ div >
109+ < div className = "text-xs" > of train ITALO9512 departing tomorrow?</ div >
110+ </ button >
111+ </ div >
62112
63- < div
64- ref = { messagesContainerRef }
65- className = "flex flex-col gap-4 h-full w-dvw items-center overflow-y-scroll"
66- >
67- { messages . map ( ( message ) => (
68- < PreviewMessage
69- key = { message . id }
70- chatId = { id }
71- role = { message . role }
72- content = { message . content }
73- attachments = { message . experimental_attachments }
74- toolInvocations = { message . toolInvocations }
113+ < div
114+ ref = { messagesContainerRef }
115+ className = "flex flex-col gap-4 h-full w-full max-w-2xl mx-auto overflow-y-scroll custom-scrollbar pb-32"
116+ >
117+ { messages . map ( ( message ) => (
118+ < PreviewMessage
119+ key = { message . id }
120+ chatId = { id }
121+ role = { message . role }
122+ content = { message . content }
123+ attachments = { message . experimental_attachments }
124+ toolInvocations = { message . toolInvocations }
125+ />
126+ ) ) }
127+
128+ < div
129+ ref = { messagesEndRef }
130+ className = "shrink-0 min-w-[24px] min-h-[24px]"
75131 />
76- ) ) }
132+ </ div >
77133
78- < div
79- ref = { messagesEndRef }
80- className = "shrink-0 min-w-[24px] min-h-[24px]"
81- />
134+ < form className = "flex flex-row gap-3 fixed bottom-8 left-1/2 -translate-x-1/2 items-end w-full md:max-w-[700px] max-w-[calc(100dvw-32px)] px-6 md:px-0 z-10" >
135+ < MultimodalInput
136+ input = { input }
137+ setInput = { setInput }
138+ handleSubmit = { handleSubmit }
139+ isLoading = { isLoading }
140+ stop = { stop }
141+ attachments = { attachments }
142+ setAttachments = { setAttachments }
143+ messages = { messages }
144+ append = { append }
145+ />
146+ </ form >
82147 </ div >
83-
84- < form className = "flex flex-row gap-2 relative items-end w-full md:max-w-[500px] max-w-[calc(100dvw-32px) px-4 md:px-0" >
85- < MultimodalInput
86- input = { input }
87- setInput = { setInput }
88- handleSubmit = { handleSubmit }
89- isLoading = { isLoading }
90- stop = { stop }
91- attachments = { attachments }
92- setAttachments = { setAttachments }
93- messages = { messages }
94- append = { append }
95- />
96- </ form >
97- </ div >
148+ ) }
98149 </ div >
99150 ) ;
100151}
0 commit comments