Files
Wdipl-react/components/portfolio/PortfolioTestimonial.tsx

71 lines
2.2 KiB
TypeScript
Raw Normal View History

import React from "react";
import { motion } from "framer-motion";
import { Star } from "lucide-react";
interface PortfolioTestimonialProps {
logo: string | React.ReactNode; // can be an image URL or React component
alt?: string;
rating?: number; // default 5
testimonial: string;
clientName: string;
clientRole: string;
maxWidth?: string; // optional, e.g., "max-w-4xl"
}
const PortfolioTestimonial: React.FC<PortfolioTestimonialProps> = ({
logo,
alt = "Client Logo",
rating = 5,
testimonial,
clientName,
clientRole,
maxWidth = "max-w-4xl",
}) => {
return (
<section className="py-24 bg-card/30">
<div className="container mx-auto px-4 lg:px-6">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className={`mx-auto text-center ${maxWidth}`}
>
<div className="bg-card/50 rounded-2xl p-12 border border-border/50">
{/* Logo */}
{typeof logo === "string" ? (
<div className="flex justify-center mb-8">
<img src={logo} alt={alt} className="h-12 w-auto object-contain" />
</div>
) : (
<div className="flex justify-center mb-8">{logo}</div>
)}
{/* Rating */}
<div className="flex justify-center mb-8">
<div className="flex text-yellow-400">
{[...Array(rating)].map((_, i) => (
<Star key={i} className="w-6 h-6 fill-current" />
))}
</div>
</div>
{/* Testimonial */}
<blockquote className="text-2xl lg:text-3xl text-foreground mb-8 leading-relaxed italic">
{testimonial}
</blockquote>
{/* Client Info */}
<div className="flex flex-col items-center">
<div className="text-lg font-semibold text-foreground">{clientName}</div>
<div className="text-muted-foreground">{clientRole}</div>
</div>
</div>
</motion.div>
</div>
</section>
);
};
export default PortfolioTestimonial;