Skip to content

Commit 3bc5da2

Browse files
authored
Merge pull request #1512 from hrx01-dev/testinomial-update
Replaced testimonial in the testimonial section and applied requested changes
2 parents 2ad1771 + 04f7a73 commit 3bc5da2

6 files changed

Lines changed: 183 additions & 150 deletions

File tree

package-lock.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/testimonials/TestimonialCard.tsx

Lines changed: 74 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import React from "react";
22
import { motion } from "framer-motion";
33
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
44
import { useSafeColorMode } from "../../utils/useSafeColorMode";
5-
import { ExternalLink, Quote } from "lucide-react";
5+
66

77
interface TestimonialCardProps {
88
name: string;
99
username: string;
1010
content: string;
1111
date: string;
1212
avatar: string;
13-
link: string;
13+
gradient?: string;
14+
borderColor?: string;
1415
}
1516

1617
const TestimonialCard: React.FC<TestimonialCardProps> = ({
@@ -19,122 +20,99 @@ const TestimonialCard: React.FC<TestimonialCardProps> = ({
1920
content,
2021
date,
2122
avatar,
22-
link,
23+
gradient,
24+
borderColor,
2325
}) => {
2426
const { colorMode, isDark } = useSafeColorMode();
2527

26-
const formatLinkDisplay = (url: string) => {
27-
try {
28-
const urlObj = new URL(url);
29-
return urlObj.hostname + urlObj.pathname;
30-
} catch {
31-
return url;
28+
const getBackgroundStyle = () => {
29+
let colorStop = "";
30+
if (gradient === "bg-pink-100") {
31+
colorStop = "rgba(244, 194, 214, 0.35)"; // Pink
32+
} else if (gradient === "bg-purple-100") {
33+
colorStop = "rgba(191, 190, 255, 0.35)"; // Blue/Lavender
34+
} else {
35+
colorStop = "rgba(165, 243, 252, 0.35)"; // Cyan
3236
}
37+
38+
return {
39+
background: `
40+
radial-gradient(
41+
ellipse 600px 500px at 10% 85%,
42+
${colorStop} 0%,
43+
rgba(255, 255, 255, 0) 70%
44+
),
45+
linear-gradient(
46+
135deg,
47+
rgba(255, 255, 255, 0.95) 0%,
48+
rgba(255, 255, 255, 0.9) 100%
49+
)
50+
`,
51+
backdropFilter: "blur(4px)",
52+
WebkitBackdropFilter: "blur(4px)",
53+
border: "1px solid rgba(200, 200, 220, 0.4)",
54+
};
3355
};
3456

3557
return (
3658
<motion.div
3759
initial={{ opacity: 0, y: 20 }}
3860
animate={{ opacity: 1, y: 0 }}
3961
exit={{ opacity: 0, y: -20 }}
40-
whileHover={{ y: -5 }}
62+
whileHover={{ y: -8 }}
4163
transition={{ duration: 0.3 }}
42-
className={`group relative h-full overflow-hidden rounded-2xl border backdrop-blur-sm transition-all duration-300 hover:shadow-2xl ${
43-
isDark
44-
? "border-gray-700/50 bg-gray-900/80 shadow-xl"
45-
: "border-gray-200/50 bg-white/90 shadow-lg"
46-
}`}
64+
className={`group relative h-full w-full overflow-hidden rounded-3xl min-h-[550px] flex flex-col justify-between p-8`}
65+
style={getBackgroundStyle()}
4766
>
48-
{/* Gradient Background */}
49-
<div className="absolute inset-0 bg-gradient-to-br from-purple-500/5 via-blue-500/5 to-pink-500/5" />
50-
51-
{/* Quote Icon */}
52-
<div className="absolute top-4 right-4 opacity-20">
53-
<Quote size={32} className="text-purple-500" />
54-
</div>
67+
{/* Subtle glossy overlay */}
68+
<div
69+
className="absolute inset-0 rounded-3xl pointer-events-none"
70+
style={{
71+
background: `linear-gradient(135deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0.2) 40%, transparent 70%)`,
72+
}}
73+
/>
5574

56-
<div className="relative flex h-full flex-col p-6">
57-
{/* Header */}
58-
<div className="mb-6 flex items-center gap-4">
59-
<div className="relative shrink-0">
60-
<Avatar className="h-16 w-16 overflow-hidden border-2 border-gradient-to-r from-purple-500 to-pink-500 bg-white/90 shadow-md">
61-
<AvatarImage src={avatar} className="h-full w-full scale-[2.3] object-cover transition-transform duration-500" />
62-
<AvatarFallback className="bg-gradient-to-br from-purple-500 to-pink-500 text-white font-semibold">
63-
{name.charAt(0)}
64-
</AvatarFallback>
65-
</Avatar>
66-
<div className="absolute bottom-0 right-0 h-4 w-4 rounded-full border-2 border-white bg-green-500 shadow-sm" />
67-
</div>
68-
<div className="flex-1">
69-
<h3 className={`text-lg font-bold ${
70-
isDark ? "text-white" : "text-gray-900"
71-
}`}>
72-
{name}
73-
</h3>
74-
<p className={`text-sm ${
75-
isDark ? "text-gray-400" : "text-gray-500"
76-
}`}>
77-
@{username}
78-
</p>
79-
</div>
80-
</div>
75+
{/* Soft shadow */}
76+
<div className="absolute inset-0 rounded-3xl pointer-events-none shadow-lg shadow-black/5" />
8177

82-
{/* Content */}
83-
<div className="flex-1">
84-
<p className={`text-base leading-relaxed ${
85-
isDark ? "text-gray-300" : "text-gray-700"
86-
}`}>
87-
{content.replace(/#\w+/g, '').trim()}
78+
<div className="relative z-10 flex flex-col h-full">
79+
{/* Testimonial Quote - Top Section */}
80+
<div className="mb-12">
81+
<p className="text-2xl leading-relaxed font-semibold text-gray-900 tracking-tight">
82+
"{content.replace(/#\w+/g, '').trim()}"
8883
</p>
8984
</div>
9085

91-
{/* Footer */}
92-
<div className={`mt-6 space-y-4 border-t pt-4 ${
93-
isDark ? "border-gray-700/50" : "border-gray-200/50"
94-
}`}>
95-
{/* Hashtags */}
96-
<div className="flex flex-wrap gap-2">
97-
{content.match(/#\w+/g)?.map((hashtag, index) => (
98-
<span
99-
key={index}
100-
className={`rounded-full px-3 py-1 text-xs font-medium transition-colors hover:scale-105 ${
101-
isDark
102-
? "bg-blue-500/20 text-blue-400 hover:bg-blue-500/30"
103-
: "bg-blue-100 text-blue-600 hover:bg-blue-200"
104-
}`}
105-
>
106-
{hashtag}
107-
</span>
108-
))}
109-
</div>
86+
{/* Avatar and Info - Bottom Section */}
87+
<div className="mt-auto">
88+
<div className="flex items-center gap-6">
89+
{/* Large Avatar with White Background */}
90+
<Avatar className="h-20 w-20 overflow-hidden rounded-full border-3 border-white shadow-md flex-shrink-0 bg-white">
91+
<AvatarImage src={avatar} className="h-full w-full object-cover scale-125" />
92+
<AvatarFallback className="text-white font-bold text-lg bg-gradient-to-br from-purple-400 to-pink-400">
93+
{name.charAt(0)}
94+
</AvatarFallback>
95+
</Avatar>
96+
97+
<div className="flex-1">
98+
<h3 className="text-xl font-bold text-gray-900 mb-1 tracking-tight">
99+
{name}
100+
</h3>
101+
{username !== "AryanGupta" && username !== "DonaldAnyamba" && (
102+
<p className="text-sm text-gray-700 font-medium mb-3">
103+
{username === "VivienChen" ? "Founder @ Toastie (BC Y24)" :
104+
username === "DanielHan" ? "Founder @ Unsloth AI (YC W24, BC Y24)" :
105+
"AI Engineer @ Relevance AI"}
106+
</p>
107+
)}
110108

111-
{/* Link and Date */}
112-
<div className="flex items-center justify-between">
113-
<a
114-
href={link}
115-
target="_blank"
116-
rel="noopener noreferrer"
117-
className={`group/link flex items-center gap-2 text-sm font-medium transition-colors ${
118-
isDark
119-
? "text-purple-400 hover:text-purple-300"
120-
: "text-purple-600 hover:text-purple-700"
121-
}`}
122-
>
123-
<span className="truncate">{formatLinkDisplay(link)}</span>
124-
<ExternalLink size={14} className="transition-transform group-hover/link:translate-x-0.5 group-hover/link:-translate-y-0.5" />
125-
</a>
126-
<span className={`text-xs ${
127-
isDark ? "text-gray-500" : "text-gray-400"
128-
}`}>
129-
{date}
130-
</span>
109+
<div className="flex items-center gap-3 text-xs text-gray-700">
110+
<span className="font-medium">{date}</span>
111+
</div>
112+
</div>
131113
</div>
132114
</div>
133115
</div>
134-
135-
{/* Hover Effect Border */}
136-
<div className="absolute inset-0 rounded-2xl border-2 border-transparent bg-gradient-to-r from-purple-500/20 via-blue-500/20 to-pink-500/20 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
137-
style={{ mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)', maskComposite: 'xor' }} />
138116
</motion.div>
139117
);
140118
};

0 commit comments

Comments
 (0)