style: update chat widget to use warm organic modern color palette

This commit is contained in:
2026-01-10 01:02:58 +01:00
parent ae37294b06
commit eaaee17bca

View File

@@ -221,14 +221,14 @@ export default function ChatWidget() {
setIsOpen(true); setIsOpen(true);
} }
}} }}
className="fixed bottom-20 left-4 md:bottom-6 md:left-6 z-30 bg-[#5A4E42]/90 backdrop-blur-md text-white p-3 rounded-full shadow-2xl hover:bg-[#4A3F35]/90 hover:scale-110 transition-all duration-300 group cursor-pointer border border-white/10" className="fixed bottom-20 left-4 md:bottom-6 md:left-6 z-30 bg-stone-800/90 backdrop-blur-md text-stone-50 p-3 rounded-full shadow-xl hover:bg-stone-700/90 hover:scale-110 transition-all duration-300 group cursor-pointer border border-white/10"
aria-label="Open chat" aria-label="Open chat"
> >
<MessageCircle size={20} /> <MessageCircle size={20} />
<span className="absolute -top-1 -right-1 w-3 h-3 bg-[#8B7D6F] rounded-full animate-pulse shadow-lg" /> <span className="absolute -top-1 -right-1 w-3 h-3 bg-stone-400 rounded-full animate-pulse shadow-sm" />
{/* Tooltip */} {/* Tooltip */}
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-3 py-1.5 bg-black/90 text-white text-xs rounded-lg opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-[100] shadow-lg"> <span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-3 py-1.5 bg-stone-900/90 text-stone-50 text-xs rounded-lg opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-[100] shadow-lg">
Chat with AI assistant Chat with AI assistant
</span> </span>
</motion.div> </motion.div>
@@ -244,22 +244,22 @@ export default function ChatWidget() {
animate={{ opacity: 1, y: 0, scale: 1 }} animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 20, scale: 0.95 }} exit={{ opacity: 0, y: 20, scale: 0.95 }}
transition={{ type: "spring", damping: 25, stiffness: 300 }} transition={{ type: "spring", damping: 25, stiffness: 300 }}
className="fixed bottom-20 left-4 md:bottom-6 md:left-6 z-30 w-[300px] sm:w-[340px] md:w-[380px] max-w-[calc(100vw-2rem)] h-[450px] sm:h-[500px] md:h-[550px] max-h-[calc(100vh-10rem)] bg-[#f5f1e8]/85 backdrop-blur-xl rounded-2xl shadow-2xl flex flex-col overflow-hidden border border-[#8B7D6F]/30 [&_a]:text-inherit [&_a]:no-underline [&_a]:text-[#2A241F] [&_a:hover]:text-[#2A241F] [&_a:visited]:text-[#2A241F] [&_a:active]:text-[#2A241F] [&_*]:outline-none [&_*:focus]:outline-none [&_*:focus-visible]:outline-none" className="fixed bottom-20 left-4 md:bottom-6 md:left-6 z-30 w-[300px] sm:w-[340px] md:w-[380px] max-w-[calc(100vw-2rem)] h-[450px] sm:h-[500px] md:h-[550px] max-h-[calc(100vh-10rem)] bg-[#fdfcf8]/90 backdrop-blur-xl rounded-2xl shadow-2xl flex flex-col overflow-hidden border border-stone-200/50 [&_a]:text-inherit [&_a]:no-underline [&_a]:text-stone-800 [&_a:hover]:text-stone-900 [&_a:visited]:text-stone-800 [&_a:active]:text-stone-900 [&_*]:outline-none [&_*:focus]:outline-none [&_*:focus-visible]:outline-none"
> >
{/* Header */} {/* Header */}
<div className="bg-gradient-to-r from-[#5A4E42]/90 to-[#4A3F35]/90 backdrop-blur-md text-white p-3 md:p-4 flex items-center justify-between border-b border-[#6B5D4F]/30"> <div className="bg-[#f3f1e7]/80 backdrop-blur-md text-stone-800 p-3 md:p-4 flex items-center justify-between border-b border-stone-200/50">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="relative"> <div className="relative">
<div className="w-10 h-10 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center ring-2 ring-white/20 shadow-lg"> <div className="w-10 h-10 rounded-full bg-white/50 backdrop-blur-sm flex items-center justify-center ring-1 ring-stone-200 shadow-sm">
<Sparkles size={20} className="text-white" /> <Sparkles size={20} className="text-stone-600" />
</div> </div>
<span className="absolute bottom-0 right-0 w-3 h-3 bg-[#8B7D6F] rounded-full border-2 border-[#5A4E42] shadow-lg" /> <span className="absolute bottom-0 right-0 w-3 h-3 bg-stone-400 rounded-full border-2 border-[#f3f1e7] shadow-sm" />
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<h3 className="font-bold text-sm truncate text-white"> <h3 className="font-bold text-sm truncate text-stone-800">
Dennis{"'"}s AI Assistant Dennis{"'"}s AI Assistant
</h3> </h3>
<p className="text-xs text-white/90 truncate"> <p className="text-xs text-stone-500 truncate">
Always online Always online
</p> </p>
</div> </div>
@@ -268,14 +268,14 @@ export default function ChatWidget() {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={clearChat} onClick={clearChat}
className="p-2 hover:bg-white/10 rounded-lg transition-colors text-white/80 hover:text-white" className="p-2 hover:bg-stone-200/50 rounded-lg transition-colors text-stone-500 hover:text-stone-800"
title="Clear conversation" title="Clear conversation"
> >
<Trash2 size={18} /> <Trash2 size={18} />
</button> </button>
<button <button
onClick={() => setIsOpen(false)} onClick={() => setIsOpen(false)}
className="p-2 hover:bg-white/10 rounded-lg transition-colors" className="p-2 hover:bg-stone-200/50 rounded-lg transition-colors text-stone-500 hover:text-stone-800"
aria-label="Close chat" aria-label="Close chat"
> >
<X size={20} /> <X size={20} />
@@ -295,20 +295,20 @@ export default function ChatWidget() {
<div <div
className={`max-w-[80%] rounded-2xl px-4 py-2.5 backdrop-blur-sm ${ className={`max-w-[80%] rounded-2xl px-4 py-2.5 backdrop-blur-sm ${
message.sender === "user" message.sender === "user"
? "bg-gradient-to-br from-[#5A4E42] to-[#4A3F35] text-white shadow-lg" ? "bg-stone-800 text-stone-50 shadow-md"
: "bg-white/90 backdrop-blur-sm text-[#2A241F] border border-[#8B7D6F]/30 shadow-md" : "bg-white/80 backdrop-blur-sm text-stone-800 border border-stone-100 shadow-sm"
}`} }`}
> >
<p className={`text-sm whitespace-pre-wrap break-words leading-relaxed [&_a]:text-inherit [&_a]:no-underline [&_a]:text-current [&_a:hover]:text-current [&_a:visited]:text-current [&_a:active]:text-current ${ <p className={`text-sm whitespace-pre-wrap break-words leading-relaxed [&_a]:text-inherit [&_a]:no-underline [&_a]:text-current [&_a:hover]:text-current [&_a:visited]:text-current [&_a:active]:text-current ${
message.sender === "user" ? "text-white" : "text-[#2A241F]" message.sender === "user" ? "text-stone-50" : "text-stone-800"
}`}> }`}>
{message.text} {message.text}
</p> </p>
<p <p
className={`text-[10px] mt-1.5 ${ className={`text-[10px] mt-1.5 ${
message.sender === "user" message.sender === "user"
? "text-white/80" ? "text-stone-300"
: "text-[#5A4E42]/70" : "text-stone-400"
}`} }`}
> >
{message.timestamp.toLocaleTimeString([], { {message.timestamp.toLocaleTimeString([], {
@@ -327,10 +327,10 @@ export default function ChatWidget() {
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
className="flex justify-start" className="flex justify-start"
> >
<div className="bg-white/90 backdrop-blur-sm border border-[#8B7D6F]/30 rounded-2xl px-4 py-3 shadow-md"> <div className="bg-white/80 backdrop-blur-sm border border-stone-100 rounded-2xl px-4 py-3 shadow-sm">
<div className="flex gap-1.5"> <div className="flex gap-1.5">
<motion.div <motion.div
className="w-2 h-2 bg-[#5A4E42] rounded-full" className="w-2 h-2 bg-stone-400 rounded-full"
animate={{ y: [0, -8, 0] }} animate={{ y: [0, -8, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -339,7 +339,7 @@ export default function ChatWidget() {
}} }}
/> />
<motion.div <motion.div
className="w-2 h-2 bg-[#5A4E42] rounded-full" className="w-2 h-2 bg-stone-400 rounded-full"
animate={{ y: [0, -8, 0] }} animate={{ y: [0, -8, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -348,7 +348,7 @@ export default function ChatWidget() {
}} }}
/> />
<motion.div <motion.div
className="w-2 h-2 bg-[#5A4E42] rounded-full" className="w-2 h-2 bg-stone-400 rounded-full"
animate={{ y: [0, -8, 0] }} animate={{ y: [0, -8, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -365,7 +365,7 @@ export default function ChatWidget() {
</div> </div>
{/* Input */} {/* Input */}
<div className="p-3 md:p-4 bg-[#f5f1e8]/60 backdrop-blur-md border-t border-[#8B7D6F]/25"> <div className="p-3 md:p-4 bg-white/40 backdrop-blur-md border-t border-stone-200/50">
<div className="flex gap-2"> <div className="flex gap-2">
<input <input
ref={inputRef} ref={inputRef}
@@ -375,12 +375,12 @@ export default function ChatWidget() {
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
placeholder="Ask anything..." placeholder="Ask anything..."
disabled={isLoading} disabled={isLoading}
className="flex-1 px-4 py-2.5 text-sm bg-white/90 backdrop-blur-sm text-[#2A241F] rounded-full border border-[#8B7D6F]/40 focus:outline-none focus:ring-2 focus:ring-[#5A4E42]/20 focus:border-[#5A4E42]/50 focus:bg-white disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-[#8B7D6F]/70 transition-all focus-visible:ring-[#5A4E42]/20 focus-visible:border-[#5A4E42]/50" className="flex-1 px-4 py-2.5 text-sm bg-white/80 backdrop-blur-sm text-stone-800 rounded-full border border-stone-200 focus:outline-none focus:ring-2 focus:ring-stone-200 focus:border-stone-400 focus:bg-white disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-stone-400 transition-all focus-visible:ring-stone-200 focus-visible:border-stone-400"
/> />
<button <button
onClick={handleSend} onClick={handleSend}
disabled={!inputValue.trim() || isLoading} disabled={!inputValue.trim() || isLoading}
className="p-2.5 bg-gradient-to-br from-[#5A4E42] to-[#4A3F35] text-white rounded-full hover:from-[#6B5D4F] hover:to-[#5A4E42] hover:shadow-xl hover:scale-110 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 shadow-lg" className="p-2.5 bg-stone-800 text-stone-50 rounded-full hover:bg-stone-700 hover:shadow-lg hover:scale-105 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 shadow-md"
aria-label="Send message" aria-label="Send message"
> >
{isLoading ? ( {isLoading ? (
@@ -405,7 +405,7 @@ export default function ChatWidget() {
inputRef.current?.focus(); inputRef.current?.focus();
}} }}
disabled={isLoading} disabled={isLoading}
className="px-3 py-1.5 text-[10px] md:text-xs bg-white/80 backdrop-blur-sm text-[#2A241F] rounded-full hover:bg-white/95 border border-[#8B7D6F]/30 transition-all whitespace-nowrap disabled:opacity-50 flex-shrink-0 shadow-sm" className="px-3 py-1.5 text-[10px] md:text-xs bg-white/60 backdrop-blur-sm text-stone-600 rounded-full hover:bg-white hover:text-stone-900 border border-stone-200 transition-all whitespace-nowrap disabled:opacity-50 flex-shrink-0 shadow-sm"
> >
{suggestion} {suggestion}
</button> </button>