Skip to content

Commit 399b557

Browse files
feat(chat): enhance chat component with user message detection and smooth scrolling; update initial state rendering
1 parent b5b0e2d commit 399b557

File tree

4 files changed

+113
-62
lines changed

4 files changed

+113
-62
lines changed

components/custom/chat.tsx

Lines changed: 111 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
12
"use client";
23

4+
import { useEffect, useState } from "react";
35
import { Attachment, Message } from "ai";
46
import { useChat } from "ai/react";
5-
import { useState } from "react";
67

78
import { Message as PreviewMessage } from "@/components/custom/message";
89
import { 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
}

components/custom/message.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const Message = ({
3232
}) => {
3333
return (
3434
<motion.div
35-
className={`flex flex-row gap-4 px-4 w-full md:w-[500px] md:px-0 first-of-type:pt-20`}
35+
className="flex flex-row gap-4 px-4 w-full md:px-0"
3636
initial={{ y: 5, opacity: 0 }}
3737
animate={{ y: 0, opacity: 1 }}
3838
>

components/custom/multimodal-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { Textarea } from "../ui/textarea";
2121

2222
const suggestedActions = [
2323
{
24-
title: "Book a train from Rome to Florence",
24+
title: "Book a train ",
2525
label: "from Roma Termini to Firenze SMN",
2626
action: "Help me book a train from Rome to Florence",
2727
},

public/images/ir-logo.png

3.91 KB
Loading

0 commit comments

Comments
 (0)