112 lines
3.6 KiB
JavaScript
112 lines
3.6 KiB
JavaScript
import { motion } from 'framer-motion'
|
||
import { Star } from 'lucide-react'
|
||
|
||
const reviews = [
|
||
{
|
||
id: 1,
|
||
name: 'Thomas M.',
|
||
role: 'Entrepreneur',
|
||
text: 'Le forfait signature vaut chaque euro. Ambiance feutrée, coupe millimétrée — je ne vais plus ailleurs.',
|
||
rating: 5,
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Alexandre R.',
|
||
role: 'Avocat',
|
||
text: 'Barbe sculptée comme je voulais depuis des années. L’équipe est à l’écoute et très pro.',
|
||
rating: 5,
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Julien L.',
|
||
role: 'Architecte',
|
||
text: 'Détails, timing, produits : tout est au niveau d’un grand palace. RDV facile à prendre.',
|
||
rating: 5,
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'Karim D.',
|
||
role: 'Consultant',
|
||
text: 'Premier camouflage gris : naturel à souhait. On m’a expliqué l’entretien sans jargon, top.',
|
||
rating: 5,
|
||
},
|
||
{
|
||
id: 5,
|
||
name: 'Nicolas P.',
|
||
role: 'Chef de projet',
|
||
text: 'Le rasage traditionnel est une claque. Serviette chaude, zéro irritation. Je recommande les yeux fermés.',
|
||
rating: 5,
|
||
},
|
||
{
|
||
id: 6,
|
||
name: 'Hugo B.',
|
||
role: 'Photographe',
|
||
text: 'J’apprécie le calme du lieu et le fait qu’on ne soit jamais bousculé. La coupe tient bien trois semaines.',
|
||
rating: 5,
|
||
},
|
||
]
|
||
|
||
function Stars({ count }) {
|
||
return (
|
||
<div className="flex gap-0.5" aria-label={`${count} sur 5 étoiles`}>
|
||
{Array.from({ length: count }, (_, i) => (
|
||
<Star
|
||
key={i}
|
||
className="h-4 w-4 fill-barber-gold text-barber-gold"
|
||
aria-hidden
|
||
/>
|
||
))}
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default function Testimonials() {
|
||
return (
|
||
<section className="border-t border-white/5 bg-barber-stone py-20 sm:py-28">
|
||
<div className="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
|
||
<motion.div
|
||
initial={{ opacity: 0, y: 20 }}
|
||
whileInView={{ opacity: 1, y: 0 }}
|
||
viewport={{ once: true, margin: '-80px' }}
|
||
transition={{ duration: 0.55 }}
|
||
className="mb-12 text-center"
|
||
>
|
||
<p className="mb-3 text-xs font-medium uppercase tracking-[0.3em] text-barber-gold">
|
||
Témoignages
|
||
</p>
|
||
<h2 className="font-serif text-3xl font-medium text-barber-cream sm:text-4xl md:text-5xl">
|
||
Avis clients
|
||
</h2>
|
||
<p className="mx-auto mt-4 max-w-2xl text-sm text-barber-cream/60 sm:text-base">
|
||
Une communauté fidèle de professionnels et de passionnés de style — merci à tous pour la confiance
|
||
accordée au fil des années.
|
||
</p>
|
||
</motion.div>
|
||
|
||
<ul className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||
{reviews.map((r, i) => (
|
||
<motion.li
|
||
key={r.id}
|
||
initial={{ opacity: 0, y: 24 }}
|
||
whileInView={{ opacity: 1, y: 0 }}
|
||
viewport={{ once: true, margin: '-40px' }}
|
||
transition={{ delay: (i % 3) * 0.06, duration: 0.5 }}
|
||
>
|
||
<blockquote className="flex h-full flex-col rounded-lg border border-white/10 bg-barber-bg p-6">
|
||
<Stars count={r.rating} />
|
||
<p className="mt-4 flex-1 text-sm leading-relaxed text-barber-cream/80">
|
||
“{r.text}”
|
||
</p>
|
||
<footer className="mt-6 border-t border-white/10 pt-4">
|
||
<cite className="not-italic text-sm font-medium text-barber-gold">{r.name}</cite>
|
||
<p className="mt-0.5 text-xs text-barber-cream/45">{r.role}</p>
|
||
</footer>
|
||
</blockquote>
|
||
</motion.li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
</section>
|
||
)
|
||
}
|