Skip to content

Commit 0f1a5c9

Browse files
Improve AI chat UI
Remove duplicate AI button, add AI Tor image as avatar, loading state with iframe, fullscreen mobile chat, responsive sizing and onboarding UI tweaks. X-Lovable-Edit-ID: edt-00c12ebc-fd39-4ee4-99c2-a0af5583f382
2 parents 282473f + 7608b46 commit 0f1a5c9

2 files changed

Lines changed: 66 additions & 16 deletions

File tree

src/assets/ai-tor-avatar.jpg

843 KB
Loading

src/components/AIChatbot.tsx

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
import React from 'react';
22
import { motion, AnimatePresence } from 'framer-motion';
3-
import { Brain, X } from 'lucide-react';
3+
import { X, Loader2 } from 'lucide-react';
44
import { toast } from 'sonner';
5+
import aiTorAvatar from '@/assets/ai-tor-avatar.jpg';
56

67
const AIChatbot = () => {
78
const [isOpen, setIsOpen] = React.useState(false);
9+
const [isLoading, setIsLoading] = React.useState(true);
810

911
const handleOpen = () => {
1012
setIsOpen(true);
13+
setIsLoading(true);
1114
toast.info('AI Assistant Loading', {
1215
description: 'Opening AI Tor Assistant...'
1316
});
1417
};
1518

19+
const handleIframeLoad = () => {
20+
setIsLoading(false);
21+
};
22+
1623
return (
1724
<>
18-
{/* Dark overlay for mobile when chat is open */}
25+
{/* Dark overlay when chat is open */}
1926
<AnimatePresence>
2027
{isOpen && (
2128
<motion.div
2229
initial={{ opacity: 0 }}
2330
animate={{ opacity: 1 }}
2431
exit={{ opacity: 0 }}
2532
onClick={() => setIsOpen(false)}
26-
className="fixed inset-0 z-40 bg-black/60 backdrop-blur-sm sm:hidden"
33+
className="fixed inset-0 z-40 bg-black/70 backdrop-blur-sm"
2734
/>
2835
)}
2936
</AnimatePresence>
@@ -34,38 +41,49 @@ const AIChatbot = () => {
3441
animate={{ opacity: 1, scale: 1 }}
3542
transition={{ delay: 0.5 }}
3643
onClick={handleOpen}
37-
className="fixed bottom-20 right-4 sm:bottom-24 sm:right-8 z-40 p-3 sm:p-4
44+
className="fixed bottom-20 right-4 sm:bottom-24 sm:right-8 z-40
3845
bg-gradient-to-br from-alien-gold to-alien-gold-dark backdrop-blur-md
39-
border-2 border-alien-gold-light rounded-full text-alien-space-dark
46+
border-2 border-alien-gold-light rounded-full
4047
hover:scale-110 transition-all duration-300
41-
shadow-2xl hover:shadow-alien-gold/50 ai-button-pulse"
48+
shadow-2xl hover:shadow-alien-gold/50 ai-button-pulse
49+
overflow-hidden w-14 h-14 sm:w-16 sm:h-16"
4250
aria-label="Open AI Assistant"
4351
>
44-
<Brain className="h-6 w-6 sm:h-7 sm:w-7" />
52+
<img
53+
src={aiTorAvatar}
54+
alt="AI Tor"
55+
className="w-full h-full object-cover"
56+
/>
4557
</motion.button>
4658

47-
{/* Chat Window */}
59+
{/* Chat Window - Fullscreen on mobile */}
4860
<AnimatePresence>
4961
{isOpen && (
5062
<motion.div
5163
initial={{ opacity: 0, y: 100, scale: 0.8 }}
5264
animate={{ opacity: 1, y: 0, scale: 1 }}
5365
exit={{ opacity: 0, y: 100, scale: 0.8 }}
5466
transition={{ duration: 0.3 }}
55-
className="fixed bottom-4 right-4 sm:bottom-24 sm:right-8 z-50
56-
w-[calc(100vw-2rem)] sm:w-[380px] md:w-[420px]
57-
h-[calc(100vh-6rem)] sm:h-[550px] md:h-[600px]
58-
max-w-[420px] max-h-[calc(100vh-4rem)] sm:max-h-[calc(100vh-8rem)]
67+
className="fixed z-50
68+
inset-0 sm:inset-auto
69+
sm:bottom-24 sm:right-8
70+
sm:w-[380px] md:w-[420px]
71+
sm:h-[550px] md:h-[600px]
72+
sm:max-h-[calc(100vh-8rem)]
5973
bg-alien-space-dark/98 backdrop-blur-xl
60-
border-2 border-alien-gold/40 rounded-2xl
74+
sm:border-2 border-alien-gold/40 sm:rounded-2xl
6175
shadow-2xl overflow-hidden chat-glow"
6276
>
6377
{/* Header */}
6478
<div className="bg-gradient-to-r from-alien-space-dark via-alien-space/90 to-alien-space-dark
6579
border-b border-alien-gold/30 p-3 sm:p-4 flex items-center justify-between">
6680
<div className="flex items-center gap-3">
67-
<div className="p-2 bg-gradient-to-br from-alien-gold/30 to-alien-green/20 rounded-full">
68-
<Brain className="h-5 w-5 text-alien-gold" />
81+
<div className="w-10 h-10 sm:w-11 sm:h-11 rounded-full overflow-hidden border-2 border-alien-gold/50">
82+
<img
83+
src={aiTorAvatar}
84+
alt="AI Tor"
85+
className="w-full h-full object-cover"
86+
/>
6987
</div>
7088
<div>
7189
<h3 className="text-alien-gold font-bold font-nasalization text-sm sm:text-base">
@@ -81,20 +99,52 @@ const AIChatbot = () => {
8199
</div>
82100
<button
83101
onClick={() => setIsOpen(false)}
84-
className="p-1.5 hover:bg-alien-gold/20 rounded-lg transition-colors"
102+
className="p-2 hover:bg-alien-gold/20 rounded-lg transition-colors"
85103
aria-label="Close chat"
86104
>
87105
<X className="h-5 w-5 text-alien-gold" />
88106
</button>
89107
</div>
90108

109+
{/* Loading State */}
110+
<AnimatePresence>
111+
{isLoading && (
112+
<motion.div
113+
initial={{ opacity: 0 }}
114+
animate={{ opacity: 1 }}
115+
exit={{ opacity: 0 }}
116+
className="absolute inset-0 top-14 sm:top-16 flex flex-col items-center justify-center
117+
bg-alien-space-dark/95 z-10"
118+
>
119+
<div className="relative">
120+
<div className="w-20 h-20 rounded-full overflow-hidden border-2 border-alien-gold/50 mb-4">
121+
<img
122+
src={aiTorAvatar}
123+
alt="AI Tor Loading"
124+
className="w-full h-full object-cover animate-pulse"
125+
/>
126+
</div>
127+
<Loader2 className="absolute -bottom-1 -right-1 h-8 w-8 text-alien-gold animate-spin" />
128+
</div>
129+
<p className="text-alien-gold font-nasalization text-sm mt-4">Loading AI Tor...</p>
130+
<div className="flex gap-1 mt-3">
131+
<span className="w-2 h-2 bg-alien-gold rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
132+
<span className="w-2 h-2 bg-alien-gold rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
133+
<span className="w-2 h-2 bg-alien-gold rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
134+
</div>
135+
</motion.div>
136+
)}
137+
</AnimatePresence>
138+
91139
{/* iframe Content */}
92140
<iframe
93141
src="https://aitor.lovable.app/"
94142
className="w-full h-[calc(100%-3.5rem)] sm:h-[calc(100%-4rem)] border-none bg-alien-space-dark"
95143
title="AI Tor Assistant"
96144
allow="microphone; camera"
145+
onLoad={handleIframeLoad}
97146
onError={() => {
147+
setIsLoading(false);
98148
toast.error('AI Assistant Error', {
99149
description: 'Failed to load AI assistant. Please try again.'
100150
});

0 commit comments

Comments
 (0)