style: enhance glassmorphism for projects and chat widget with improved transparency and readability

This commit is contained in:
2026-01-10 01:07:49 +01:00
parent 792f0c8aae
commit 98f1a07b08
2 changed files with 31 additions and 31 deletions

View File

@@ -244,13 +244,13 @@ export default function ChatWidget() {
animate={{ opacity: 1, y: 0, scale: 1, filter: "blur(0px)" }} animate={{ opacity: 1, y: 0, scale: 1, filter: "blur(0px)" }}
exit={{ opacity: 0, y: 20, scale: 0.95, filter: "blur(10px)" }} exit={{ opacity: 0, y: 20, scale: 0.95, filter: "blur(10px)" }}
transition={{ type: "spring", damping: 30, stiffness: 400 }} transition={{ type: "spring", damping: 30, stiffness: 400 }}
className="fixed bottom-20 left-4 right-4 md:bottom-24 md:left-6 md:right-auto z-30 md:w-[380px] h-[60vh] md:h-[550px] max-h-[600px] bg-[#fdfcf8]/60 backdrop-blur-2xl saturate-150 rounded-2xl shadow-[0_12px_40px_rgba(41,37,36,0.15)] flex flex-col overflow-hidden border border-white/40 ring-1 ring-white/50" className="fixed bottom-20 left-4 right-4 md:bottom-24 md:left-6 md:right-auto z-30 md:w-[380px] h-[60vh] md:h-[550px] max-h-[600px] bg-[#fdfcf8]/30 backdrop-blur-2xl saturate-150 rounded-2xl shadow-[0_12px_40px_rgba(41,37,36,0.15)] flex flex-col overflow-hidden border border-white/40 ring-1 ring-white/50"
> >
{/* Header */} {/* Header */}
<div className="bg-white/40 backdrop-blur-lg text-stone-800 p-4 flex items-center justify-between border-b border-white/30"> <div className="bg-white/20 backdrop-blur-md text-stone-800 p-4 flex items-center justify-between border-b border-white/20">
<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-gradient-to-br from-stone-100 to-white flex items-center justify-center ring-1 ring-white shadow-sm"> <div className="w-10 h-10 rounded-full bg-gradient-to-br from-stone-100/80 to-white/80 flex items-center justify-center ring-1 ring-white shadow-sm backdrop-blur-sm">
<Sparkles size={18} className="text-stone-600" /> <Sparkles size={18} className="text-stone-600" />
</div> </div>
<span className="absolute bottom-0 right-0 w-2.5 h-2.5 bg-emerald-400 rounded-full border-2 border-white shadow-sm" /> <span className="absolute bottom-0 right-0 w-2.5 h-2.5 bg-emerald-400 rounded-full border-2 border-white shadow-sm" />
@@ -295,12 +295,12 @@ export default function ChatWidget() {
<div <div
className={`max-w-[85%] rounded-2xl px-4 py-3 backdrop-blur-md shadow-sm ${ className={`max-w-[85%] rounded-2xl px-4 py-3 backdrop-blur-md shadow-sm ${
message.sender === "user" message.sender === "user"
? "bg-stone-800/90 text-stone-50" ? "bg-stone-800/90 text-stone-50 ring-1 ring-white/10"
: "bg-white/60 text-stone-800 border border-white/50" : "bg-white/70 text-stone-800 border border-white/50 ring-1 ring-white/40"
}`} }`}
> >
<p className={`text-sm whitespace-pre-wrap break-words leading-relaxed ${ <p className={`text-sm whitespace-pre-wrap break-words leading-relaxed ${
message.sender === "user" ? "text-stone-50 font-light" : "text-stone-800 font-normal" message.sender === "user" ? "text-stone-50 font-light" : "text-stone-800 font-medium"
}`}> }`}>
{message.text} {message.text}
</p> </p>
@@ -308,7 +308,7 @@ export default function ChatWidget() {
className={`text-[10px] mt-1.5 ${ className={`text-[10px] mt-1.5 ${
message.sender === "user" message.sender === "user"
? "text-stone-400" ? "text-stone-400"
: "text-stone-400" : "text-stone-500"
}`} }`}
> >
{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/50 backdrop-blur-sm border border-white/40 rounded-2xl px-4 py-3 shadow-sm"> <div className="bg-white/60 backdrop-blur-md border border-white/40 rounded-2xl px-4 py-3 shadow-sm ring-1 ring-white/40">
<div className="flex gap-1.5"> <div className="flex gap-1.5">
<motion.div <motion.div
className="w-1.5 h-1.5 bg-stone-400 rounded-full" className="w-1.5 h-1.5 bg-stone-500 rounded-full"
animate={{ y: [0, -6, 0] }} animate={{ y: [0, -6, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -339,7 +339,7 @@ export default function ChatWidget() {
}} }}
/> />
<motion.div <motion.div
className="w-1.5 h-1.5 bg-stone-400 rounded-full" className="w-1.5 h-1.5 bg-stone-500 rounded-full"
animate={{ y: [0, -6, 0] }} animate={{ y: [0, -6, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -348,7 +348,7 @@ export default function ChatWidget() {
}} }}
/> />
<motion.div <motion.div
className="w-1.5 h-1.5 bg-stone-400 rounded-full" className="w-1.5 h-1.5 bg-stone-500 rounded-full"
animate={{ y: [0, -6, 0] }} animate={{ y: [0, -6, 0] }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
@@ -365,7 +365,7 @@ export default function ChatWidget() {
</div> </div>
{/* Input */} {/* Input */}
<div className="p-4 bg-white/30 backdrop-blur-xl border-t border-white/30"> <div className="p-4 bg-white/20 backdrop-blur-xl border-t border-white/20">
<div className="flex gap-2"> <div className="flex gap-2">
<input <input
ref={inputRef} ref={inputRef}
@@ -375,7 +375,7 @@ export default function ChatWidget() {
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
placeholder="Ask anything..." placeholder="Ask anything..."
disabled={isLoading} disabled={isLoading}
className="flex-1 px-4 py-3 text-sm bg-white/60 backdrop-blur-sm text-stone-800 rounded-xl border border-white/50 focus:outline-none focus:ring-2 focus:ring-stone-200/50 focus:border-stone-400/50 focus:bg-white/80 disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-stone-400 transition-all shadow-inner" className="flex-1 px-4 py-3 text-sm bg-white/50 backdrop-blur-sm text-stone-800 rounded-xl border border-white/40 focus:outline-none focus:ring-2 focus:ring-stone-200/50 focus:border-stone-400/50 focus:bg-white/70 disabled:opacity-50 disabled:cursor-not-allowed placeholder:text-stone-500 transition-all shadow-inner"
/> />
<button <button
onClick={handleSend} onClick={handleSend}
@@ -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-xs font-medium bg-white/40 backdrop-blur-md text-stone-600 rounded-lg hover:bg-white/70 hover:text-stone-900 border border-white/40 transition-all whitespace-nowrap disabled:opacity-50 flex-shrink-0 shadow-sm" className="px-3 py-1.5 text-xs font-medium bg-white/40 backdrop-blur-md text-stone-700 rounded-lg hover:bg-white/60 hover:text-stone-900 border border-white/40 transition-all whitespace-nowrap disabled:opacity-50 flex-shrink-0 shadow-sm"
> >
{suggestion} {suggestion}
</button> </button>

View File

@@ -99,23 +99,23 @@ const Projects = () => {
key={project.id} key={project.id}
variants={fadeInUp} variants={fadeInUp}
whileHover={{ whileHover={{
y: -12, y: -8,
transition: { duration: 0.5, ease: "easeOut" }, transition: { duration: 0.4, ease: "easeOut" },
}} }}
className="group relative flex flex-col bg-white rounded-2xl overflow-hidden shadow-sm hover:shadow-2xl transition-all duration-700 ease-out border border-stone-100 hover:border-stone-200" className="group relative flex flex-col bg-white/40 backdrop-blur-xl backdrop-saturate-150 rounded-2xl overflow-hidden shadow-[0_4px_20px_rgba(0,0,0,0.02)] hover:shadow-[0_20px_40px_rgba(0,0,0,0.06)] transition-all duration-500 ease-out border border-white/50 ring-1 ring-white/30"
> >
{/* Project Cover / Header */} {/* Project Cover / Header */}
<div className="relative aspect-[4/3] overflow-hidden bg-gradient-to-br from-stone-50 to-stone-100"> <div className="relative aspect-[4/3] overflow-hidden bg-stone-100/50">
{project.imageUrl ? ( {project.imageUrl ? (
<Image <Image
src={project.imageUrl} src={project.imageUrl}
alt={project.title} alt={project.title}
fill fill
className="object-cover transition-transform duration-1000 ease-out group-hover:scale-110" className="object-cover transition-transform duration-1000 ease-out group-hover:scale-105"
/> />
) : ( ) : (
<div className="absolute inset-0 bg-gradient-to-br from-stone-100 to-stone-200 flex items-center justify-center p-8 group-hover:from-stone-50 group-hover:to-stone-100 transition-colors duration-700 ease-out"> <div className="absolute inset-0 bg-gradient-to-br from-stone-100/50 to-stone-200/50 flex items-center justify-center p-8 group-hover:from-stone-50/50 group-hover:to-stone-100/50 transition-colors duration-700 ease-out">
<div className="w-full h-full border-2 border-dashed border-stone-300 rounded-xl flex items-center justify-center"> <div className="w-full h-full border-2 border-dashed border-stone-300/50 rounded-xl flex items-center justify-center">
<Layers className="text-stone-300 w-12 h-12" /> <Layers className="text-stone-300 w-12 h-12" />
</div> </div>
<div className="absolute inset-0 bg-gradient-to-tr from-liquid-mint/10 via-transparent to-liquid-rose/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500" /> <div className="absolute inset-0 bg-gradient-to-tr from-liquid-mint/10 via-transparent to-liquid-rose/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
@@ -123,13 +123,13 @@ const Projects = () => {
)} )}
{/* Overlay Links */} {/* Overlay Links */}
<div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity duration-700 ease-out flex items-center justify-center gap-4 backdrop-blur-sm"> <div className="absolute inset-0 bg-stone-900/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500 ease-out flex items-center justify-center gap-4 backdrop-blur-[2px]">
{project.github && ( {project.github && (
<a <a
href={project.github} href={project.github}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="p-3 bg-white rounded-full text-stone-900 hover:scale-110 transition-all duration-500 ease-out hover:shadow-lg" className="p-3 bg-white/90 backdrop-blur-md rounded-full text-stone-800 hover:scale-110 transition-all duration-300 ease-out shadow-lg hover:shadow-xl border border-white/50"
aria-label="GitHub" aria-label="GitHub"
> >
<Github size={20} /> <Github size={20} />
@@ -140,7 +140,7 @@ const Projects = () => {
href={project.live} href={project.live}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="p-3 bg-white rounded-full text-stone-900 hover:scale-110 transition-all duration-500 ease-out hover:shadow-lg" className="p-3 bg-white/90 backdrop-blur-md rounded-full text-stone-800 hover:scale-110 transition-all duration-300 ease-out shadow-lg hover:shadow-xl border border-white/50"
aria-label="Live Demo" aria-label="Live Demo"
> >
<ExternalLink size={20} /> <ExternalLink size={20} />
@@ -152,15 +152,15 @@ const Projects = () => {
{/* Content */} {/* Content */}
<div className="flex flex-col flex-1 p-6"> <div className="flex flex-col flex-1 p-6">
<div className="flex justify-between items-start mb-3"> <div className="flex justify-between items-start mb-3">
<h3 className="text-xl font-bold text-stone-900 group-hover:text-stone-700 transition-colors duration-500"> <h3 className="text-xl font-bold text-stone-900 group-hover:text-stone-700 transition-colors duration-300 tracking-tight">
{project.title} {project.title}
</h3> </h3>
<span className="text-xs font-mono text-stone-400 bg-stone-100 px-2 py-1 rounded"> <span className="text-xs font-mono text-stone-500 bg-white/60 border border-stone-200/50 px-2 py-1 rounded backdrop-blur-sm">
{new Date(project.date).getFullYear()} {new Date(project.date).getFullYear()}
</span> </span>
</div> </div>
<p className="text-stone-700 text-sm leading-relaxed mb-6 line-clamp-3 flex-1"> <p className="text-stone-700 font-medium text-sm leading-relaxed mb-6 line-clamp-3 flex-1 opacity-90">
{project.description} {project.description}
</p> </p>
@@ -169,13 +169,13 @@ const Projects = () => {
{project.tags.slice(0, 3).map((tag, tIdx) => ( {project.tags.slice(0, 3).map((tag, tIdx) => (
<span <span
key={`${project.id}-${tag}-${tIdx}`} key={`${project.id}-${tag}-${tIdx}`}
className="text-xs px-2.5 py-1 bg-stone-50 border border-stone-100 rounded-md text-stone-600 font-medium hover:bg-stone-100 hover:border-stone-200 transition-all duration-400 ease-out" className="text-xs px-2.5 py-1 bg-white/50 border border-white/60 rounded-md text-stone-700 font-medium hover:bg-white/80 hover:border-white transition-all duration-300 ease-out shadow-sm"
> >
{tag} {tag}
</span> </span>
))} ))}
{project.tags.length > 3 && ( {project.tags.length > 3 && (
<span className="text-xs px-2 py-1 text-stone-400"> <span className="text-xs px-2 py-1 text-stone-500 font-medium">
+ {project.tags.length - 3} + {project.tags.length - 3}
</span> </span>
)} )}
@@ -183,12 +183,12 @@ const Projects = () => {
<Link <Link
href={`/projects/${project.title.toLowerCase().replace(/\s+/g, "-")}`} href={`/projects/${project.title.toLowerCase().replace(/\s+/g, "-")}`}
className="inline-flex items-center text-sm font-semibold text-stone-900 hover:gap-3 transition-all duration-500 ease-out group/link" className="inline-flex items-center text-sm font-bold text-stone-800 hover:gap-3 transition-all duration-300 ease-out group/link"
> >
Read more{" "} Read more{" "}
<ArrowRight <ArrowRight
size={16} size={16}
className="ml-1 transition-transform duration-500 ease-out group-hover/link:translate-x-2" className="ml-1 transition-transform duration-300 ease-out group-hover/link:translate-x-1"
/> />
</Link> </Link>
</div> </div>