Skip to content

Commit 95c522c

Browse files
Merge pull request #370 from itsdevansh5/main
updated botwidget responsiveness for all screentype
2 parents 2908c88 + c535916 commit 95c522c

File tree

2 files changed

+84
-65
lines changed

2 files changed

+84
-65
lines changed

app/globals.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,5 @@
315315
display: none;
316316
}
317317
*/
318+
319+

components/BotWidget.tsx

Lines changed: 82 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function BotWidget() {
1111
const [messages, setMessages] = useState([
1212
{
1313
role: "bot",
14-
content: "👋 Hi! Im your DSAMate Bot. Tell me what youve done so far!",
14+
content: "👋 Hi! I'm your DSAMate Bot. Tell me what you've done so far!",
1515
},
1616
]);
1717
const [loading, setLoading] = useState(false);
@@ -72,88 +72,101 @@ export default function BotWidget() {
7272
};
7373

7474
return (
75-
<div ref={chatRef} className="fixed bottom-10 right-6 z-50">
75+
<div ref={chatRef} className="fixed bottom-4 right-4 sm:bottom-6 sm:right-6 z-40">
76+
{/* Bot Button - Responsive sizing */}
7677
<button
7778
onClick={() => setOpen(!open)}
78-
className="bg-blue-600 w-16 h-16 rounded-full shadow-lg flex items-center justify-center"
79+
className="w-12 h-12 sm:w-16 sm:h-16 md:w-16 md:h-16 lg:w-16 lg:h-16
80+
bg-blue-600 rounded-full shadow-lg hover:shadow-xl transition-all duration-300
81+
flex items-center justify-center hover:bg-blue-700 active:scale-95"
7982
>
8083
<Image
8184
src="/assets/bot.gif"
8285
alt="BOT"
8386
width={80}
8487
height={80}
85-
className="object-contain"
88+
className="w-full h-full object-contain p-1"
8689
unoptimized
8790
/>
8891
</button>
8992

93+
{/* Chat Window - Responsive positioning and sizing */}
9094
{open && (
91-
<div className="mt-2 w-96 bg-white rounded-xl shadow-md border max-h-[70vh] flex flex-col">
92-
<div className="flex-1 p-4 overflow-y-auto max-h-[50vh] space-y-2">
95+
<div className="absolute bottom-16 right-0 sm:bottom-20 sm:right-0
96+
w-72 sm:w-80 md:w-96 lg:w-[400px] xl:w-[420px]
97+
h-[50vh] sm:h-[60vh] md:h-[65vh] max-h-[450px]
98+
bg-white rounded-xl shadow-lg border flex flex-col">
99+
100+
{/* Messages Container - Responsive padding and text sizing */}
101+
<div className="flex-1 p-3 sm:p-4 md:p-5 overflow-y-auto space-y-3">
93102
{messages.map((msg, i) => {
94-
let contentElement;
103+
let contentElement;
95104

96-
// Try to parse JSON
97-
try {
98-
const data = JSON.parse(msg.content);
99-
if (Array.isArray(data) && data[0]?.title && data[0]?.description) {
100-
// Render as question cards
101-
contentElement = (
102-
<div className="space-y-3">
103-
{data.map((q, idx) => (
104-
<div
105-
key={idx}
106-
className="border rounded-lg p-3 bg-white text-black shadow-sm"
107-
>
108-
<h3 className="font-bold text-blue-600">{q.title}</h3>
109-
<p className="text-sm mt-1">{q.description}</p>
110-
<p className="text-xs mt-2 text-gray-500">
111-
<b>Topic:</b> {q.topic} | <b>Level:</b> {q.level}
112-
</p>
113-
</div>
114-
))}
115-
</div>
116-
);
117-
} else {
118-
contentElement = <span>{msg.content}</span>;
119-
}
120-
} catch {
121-
// Parse markdown-style formatting
122-
const formattedContent = msg.content
123-
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // **bold**
124-
.replace(/\*(.*?)\*/g, '<em>$1</em>') // *italic*
125-
.replace(/^(\d+\.)\s/gm, '<strong>$1</strong> '); // numbered lists
126-
127-
contentElement = (
128-
<span
129-
dangerouslySetInnerHTML={{ __html: formattedContent }}
130-
/>
131-
);
132-
}
105+
// Try to parse JSON
106+
try {
107+
const data = JSON.parse(msg.content);
108+
if (Array.isArray(data) && data[0]?.title && data[0]?.description) {
109+
// Render as question cards
110+
contentElement = (
111+
<div className="space-y-2 sm:space-y-3">
112+
{data.map((q, idx) => (
113+
<div
114+
key={idx}
115+
className="border rounded-lg p-3 sm:p-4 bg-white text-black shadow-sm hover:shadow-md transition-shadow"
116+
>
117+
<h3 className="font-bold text-blue-600 text-sm sm:text-base md:text-lg">{q.title}</h3>
118+
<p className="text-sm sm:text-base md:text-lg mt-1">{q.description}</p>
119+
<p className="text-xs sm:text-sm md:text-base mt-2 text-gray-500">
120+
<b>Topic:</b> {q.topic} | <b>Level:</b> {q.level}
121+
</p>
122+
</div>
123+
))}
124+
</div>
125+
);
126+
} else {
127+
contentElement = <span>{msg.content}</span>;
128+
}
129+
} catch {
130+
// Parse markdown-style formatting
131+
const formattedContent = msg.content
132+
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // **bold**
133+
.replace(/\*(.*?)\*/g, '<em>$1</em>') // *italic*
134+
.replace(/^(\d+\.)\s/gm, '<strong>$1</strong> '); // numbered lists
135+
136+
contentElement = (
137+
<span
138+
dangerouslySetInnerHTML={{ __html: formattedContent }}
139+
/>
140+
);
141+
}
133142

134-
return (
135-
<div
136-
key={i}
137-
className={`p-2 rounded text-black text-sm whitespace-pre-line ${
138-
msg.role === "user"
139-
? "bg-blue-100 text-right"
140-
: "bg-gray-100 text-left"
141-
}`}
142-
>
143-
{contentElement}
144-
</div>
145-
);
146-
})}
143+
return (
144+
<div
145+
key={i}
146+
className={`rounded-lg text-black whitespace-pre-line transition-all
147+
p-3 sm:p-4
148+
text-sm sm:text-base
149+
${msg.role === "user"
150+
? "bg-blue-100 text-right ml-4"
151+
: "bg-gray-100 text-left mr-4"
152+
}`}
153+
>
154+
{contentElement}
155+
</div>
156+
);
157+
})}
147158
<div ref={messagesEndRef} />
148159
</div>
149160

150-
<div className="p-4 border-t">
151-
<div className="flex items-center gap-2">
161+
{/* Input Area - Responsive padding and sizing */}
162+
<div className="p-3 sm:p-4 border-t bg-gray-50">
163+
<div className="flex items-center gap-2 sm:gap-3">
152164
<Input
153165
value={input}
154166
onChange={(e) => setInput(e.target.value)}
155167
placeholder="What have you covered so far?"
156-
className="flex-grow border p-2 rounded text-black"
168+
className="flex-grow border p-2 sm:p-3 rounded-lg text-black focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all
169+
text-sm sm:text-base"
157170
disabled={loading}
158171
onKeyDown={(e) => {
159172
if (e.key === "Enter" && !loading) {
@@ -164,21 +177,25 @@ export default function BotWidget() {
164177
<button
165178
onClick={handleSend}
166179
disabled={loading}
167-
className={`p-2 rounded text-white ${
180+
className={`p-2 sm:p-3 rounded-lg text-white transition-all duration-200 ${
168181
loading
169182
? "bg-gray-400 cursor-not-allowed"
170-
: "bg-blue-600 hover:bg-blue-700"
183+
: "bg-blue-600 hover:bg-blue-700 hover:scale-105 active:scale-95 shadow-md hover:shadow-lg"
171184
}`}
172185
>
173-
<SendHorizonal size={16} />
186+
<SendHorizonal
187+
className="w-4 h-4 sm:w-5 sm:h-5"
188+
/>
174189
</button>
175190
</div>
176191
{loading && (
177-
<p className="text-sm text-gray-500 mt-2">🤖 Thinking...</p>
192+
<p className="text-gray-500 mt-2 animate-pulse text-sm">
193+
🤖 Thinking...
194+
</p>
178195
)}
179196
</div>
180197
</div>
181198
)}
182199
</div>
183200
);
184-
}
201+
}

0 commit comments

Comments
 (0)