76 lines
3.8 KiB
JavaScript
76 lines
3.8 KiB
JavaScript
import { useState } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { Image } from '@/components/ui/image';
|
|
import { Sparkles, X } from 'lucide-react';
|
|
import Owliver from '@/pages/Owliver';
|
|
|
|
const OWLIVER_URL = 'https://media.base44.com/images/public/6a653ab9436c05c43a00994f/2005ea00e_WhatsAppImage2026-07-31at35919PM.jpeg';
|
|
|
|
export default function OwliverChatBubble({ open: externalOpen, onOpenChange, showTrigger = true }) {
|
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
const open = externalOpen !== undefined ? externalOpen : internalOpen;
|
|
const setOpen = (v) => {
|
|
if (onOpenChange) onOpenChange(v);
|
|
setInternalOpen(v);
|
|
};
|
|
|
|
return (
|
|
<div className="fixed bottom-6 right-6 z-50">
|
|
<AnimatePresence mode="wait">
|
|
{!open && showTrigger ? (
|
|
<motion.button
|
|
key="pill"
|
|
initial={{ opacity: 0, y: 24 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 12, scale: 0.96 }}
|
|
transition={{ duration: 0.3 }}
|
|
onClick={() => setOpen(true)}
|
|
aria-label="Ask Owliver"
|
|
className="group flex items-center gap-3 rounded-full bg-white pl-5 pr-2 py-2 w-[min(80vw,360px)]
|
|
shadow-[0_10px_30px_rgba(10,57,223,0.22),0_2px_6px_rgba(51,63,72,0.08)]
|
|
ring-1 ring-black/5 transition-transform duration-300 hover:scale-[1.01]"
|
|
>
|
|
<Sparkles className="w-4 h-4 text-[#0A39DF] shrink-0" />
|
|
<span className="text-[15px] text-[#B5B8D3] font-medium flex-1 truncate text-left group-hover:text-[#0A39DF] transition-colors">
|
|
Build your profile
|
|
</span>
|
|
<span className="relative block w-12 h-12 rounded-full overflow-hidden ring-2 ring-[#0A39DF]/15 shadow-[0_4px_12px_rgba(10,57,223,0.35)] shrink-0">
|
|
<Image src={OWLIVER_URL} alt="Owliver" fittingType="fill" className="w-full h-full" />
|
|
</span>
|
|
</motion.button>
|
|
) : open ? (
|
|
<motion.div
|
|
key="panel"
|
|
initial={{ opacity: 0, y: 24, scale: 0.96 }}
|
|
animate={{ opacity: 1, y: 0, scale: 1 }}
|
|
exit={{ opacity: 0, y: 12, scale: 0.96 }}
|
|
transition={{ duration: 0.28 }}
|
|
className="flex flex-col w-[min(94vw,400px)] h-[min(82vh,620px)] rounded-2xl bg-white overflow-hidden
|
|
shadow-[0_18px_50px_rgba(10,57,223,0.28),0_4px_12px_rgba(51,63,72,0.12)] ring-1 ring-black/5"
|
|
>
|
|
<div className="flex items-center gap-2.5 px-4 py-3 bg-[#0A39DF] text-white shrink-0">
|
|
<span className="block w-8 h-8 rounded-full overflow-hidden ring-2 ring-white/40">
|
|
<Image src={OWLIVER_URL} alt="Owliver" fittingType="fill" className="w-full h-full" />
|
|
</span>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="text-[14px] font-bold leading-tight flex items-center gap-1.5">
|
|
Owliver <Sparkles className="w-3.5 h-3.5 text-[#F9E547]" />
|
|
</div>
|
|
<div className="text-[11px] text-white/80 leading-tight">Online · ready to chat</div>
|
|
</div>
|
|
<button onClick={() => setOpen(false)} aria-label="Close chat" className="w-8 h-8 rounded-full hover:bg-white/20 flex items-center justify-center transition-colors">
|
|
<X className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex-1 overflow-y-auto bg-[#F9FAFB] p-4">
|
|
<div className="max-w-none h-full [&>div]:max-w-none [&>div]:mx-0 [&>div]:h-full [&>div]:flex [&>div]:flex-col">
|
|
<Owliver compact />
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
) : null}
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
} |