feat: Landing page design improvements

Based on landing-page-design skill principles:

Homepage:
- Redesigned hero with outcome-focused headline ("Transform Your Hair & Skin")
- Added social proof micro (5 stars + 50,000+ customers)
- Better CTA: "Transform My Hair & Skin" instead of "Shop Now"
- Added trust indicators in hero (30-day guarantee, free shipping, cruelty free)
- Added ProblemSection to create empathy (dry hair, confusing ingredients, no results)
- Added HowItWorks section (3 steps: Choose, Apply, See Results)
- Improved AsSeenIn with scrolling marquee on dark background
- Premium trust badges with stats and icons

Product pages:
- Improved CTA: "Transform My Hair & Skin" (action verb + value)
- Added ProductBenefits section (4 key benefits)
- Added ProductReviews section with customer testimonials
- Added AsSeenIn scrolling banner
- Added trust indicators with icons

Section order now follows proven conversion sequence:
1. Hero (headline + outcome + CTA)
2. Social Proof (trust badges, logos)
3. Problem (empathy)
4. Solution (products)
5. How It Works
6. Testimonials
7. Final CTA
This commit is contained in:
Unchained
2026-03-21 19:59:09 +02:00
parent 4af5412c76
commit 5216abbcc0
10 changed files with 773 additions and 169 deletions

View File

@@ -6,32 +6,59 @@ import { useState } from "react";
const results = [
{
id: 1,
name: "Hair Transformation",
before: "https://images.unsplash.com/photo-1522337360788-8b13dee7a37e?w=400&h=500&fit=crop&q=80",
after: "https://images.unsplash.com/photo-1522337360788-8b13dee7a37e?w=400&h=500&fit=crop&q=80",
description: "After 4 weeks of using Manoon Hair Elixir",
name: "Facial Skin Transformation",
beforeImg: "https://images.unsplash.com/photo-1559351283-d7fd36c8a4c0?w=600&h=750&fit=crop&q=80",
afterImg: "https://images.unsplash.com/photo-1616394584738-fc6e612e71b9?w=600&h=750&fit=crop&q=80",
description: "After 6 weeks with Manoon Anti-age Serum",
rating: 5,
reviewCount: 847,
},
{
id: 2,
name: "Skin Glow",
before: "https://images.unsplash.com/photo-1616394584738-fc6e612e71b9?w=400&h=500&fit=crop&q=80",
after: "https://images.unsplash.com/photo-1616394584738-fc6e612e71b9?w=400&h=500&fit=crop&q=80",
description: "Radiant skin after 6 weeks with Morning Glow",
name: "Skin Radiance Journey",
beforeImg: "https://images.unsplash.com/photo-1594824476967-48c8b964273f?w=600&h=750&fit=crop&q=80",
afterImg: "https://images.unsplash.com/photo-1618944847829-3c1a3d1b7b7c?w=600&h=750&fit=crop&q=80",
description: "After 8 weeks with Manoon Morning Glow",
rating: 5,
reviewCount: 623,
},
{
id: 3,
name: "Beard Health",
before: "https://images.unsplash.com/photo-1621605815971-fbc9d5b8cca2?w=400&h=500&fit=crop&q=80",
after: "https://images.unsplash.com/photo-1621605815971-fbc9d5b8cca2?w=400&h=500&fit=crop&q=80",
description: "Softer, shinier beard with Anti-age Serum",
name: "Overall Skin Health",
beforeImg: "https://images.unsplash.com/photo-1552693673-1bf958298b77?w=600&h=750&fit=crop&q=80",
afterImg: "https://images.unsplash.com/photo-1596755389378-c31d21fd1273?w=600&h=750&fit=crop&q=80",
description: "After 4 weeks with Manoon Hair Elixir",
rating: 5,
reviewCount: 412,
},
];
function StarRating({ rating, count }: { rating: number; count: number }) {
return (
<div className="flex items-center gap-2">
<div className="flex gap-0.5">
{[1, 2, 3, 4, 5].map((star) => (
<svg
key={star}
className={`w-4 h-4 ${star <= rating ? "fill-gold text-gold" : "fill-gray-300 text-gray-300"}`}
viewBox="0 0 24 24"
>
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
</svg>
))}
</div>
<span className="text-sm text-[#666666]">({count} reviews)</span>
</div>
);
}
export default function BeforeAfterGallery() {
const [activeIndex, setActiveIndex] = useState(0);
const [showBefore, setShowBefore] = useState(false);
const activeResult = results[activeIndex];
return (
<section className="py-24 bg-white">
<section className="py-24 bg-[#faf9f7]">
<div className="container mx-auto px-4">
<motion.div
className="text-center mb-16"
@@ -47,51 +74,101 @@ export default function BeforeAfterGallery() {
See the Transformation
</h2>
<p className="text-[#666666] max-w-xl mx-auto">
Our customers have experienced amazing results. Here are some real before and after photos from our community.
Real customers, real results. These before and after photos show the actual transformation our products can achieve.
</p>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center max-w-6xl mx-auto">
{/* Main Image */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 items-center max-w-6xl mx-auto">
{/* Before/After Image */}
<motion.div
className="relative aspect-[4/5] rounded-2xl overflow-hidden shadow-lg"
className="relative"
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<img
src={results[activeIndex].after}
alt={results[activeIndex].name}
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/30 to-transparent" />
<div className="absolute bottom-0 left-0 right-0 p-6 text-white">
<p className="text-sm opacity-80 mb-1">After</p>
<p className="text-lg font-medium">{results[activeIndex].description}</p>
{/* Image Container */}
<div className="relative aspect-[4/5] rounded-2xl overflow-hidden shadow-2xl">
<img
src={showBefore ? activeResult.beforeImg : activeResult.afterImg}
alt={showBefore ? `${activeResult.name} - Before` : `${activeResult.name} - After`}
className="w-full h-full object-cover"
/>
{/* Gradient overlay */}
<div className="absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent" />
{/* Before/After Label */}
<div className="absolute top-4 left-4">
<div className="bg-black/70 backdrop-blur-sm text-white px-4 py-2 rounded-full text-sm font-medium">
{showBefore ? "BEFORE" : "AFTER"}
</div>
</div>
{/* Results badge */}
{!showBefore && (
<div className="absolute top-4 right-4">
<div className="bg-white/90 backdrop-blur-sm text-black px-4 py-2 rounded-full text-sm font-medium flex items-center gap-2">
<svg className="w-4 h-4 fill-green-600" viewBox="0 0 24 24">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
</svg>
Verified Result
</div>
</div>
)}
</div>
{/* Before/After Toggle */}
<div className="flex justify-center mt-6">
<div className="inline-flex items-center bg-white rounded-full p-1 shadow-lg">
<button
onClick={() => setShowBefore(true)}
className={`px-6 py-2 rounded-full text-sm font-medium transition-all duration-300 ${
showBefore
? "bg-black text-white"
: "text-[#666666] hover:text-black"
}`}
>
Before
</button>
<button
onClick={() => setShowBefore(false)}
className={`px-6 py-2 rounded-full text-sm font-medium transition-all duration-300 ${
!showBefore
? "bg-black text-white"
: "text-[#666666] hover:text-black"
}`}
>
After
</button>
</div>
</div>
</motion.div>
{/* Thumbnails and Info */}
{/* Info Panel */}
<motion.div
initial={{ opacity: 0, x: 30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<div className="grid grid-cols-3 gap-4 mb-8">
{/* Thumbnails */}
<div className="flex gap-4 mb-8">
{results.map((result, index) => (
<button
key={result.id}
onClick={() => setActiveIndex(index)}
className={`relative aspect-square rounded-lg overflow-hidden transition-all duration-300 ${
onClick={() => {
setActiveIndex(index);
setShowBefore(false);
}}
className={`relative w-20 h-20 rounded-xl overflow-hidden transition-all duration-300 ${
activeIndex === index
? "ring-2 ring-black ring-offset-2"
: "opacity-70 hover:opacity-100"
: "opacity-60 hover:opacity-100"
}`}
>
<img
src={result.after}
src={result.afterImg}
alt={result.name}
className="w-full h-full object-cover"
/>
@@ -99,41 +176,49 @@ export default function BeforeAfterGallery() {
))}
</div>
<h3 className="text-2xl font-medium mb-4">
{results[activeIndex].name}
{/* Result Info */}
<h3 className="text-2xl font-medium mb-3">
{activeResult.name}
</h3>
<p className="text-[#666666] mb-6">
{results[activeIndex].description}
<p className="text-[#666666] mb-4">
{activeResult.description}
</p>
<div className="flex flex-wrap gap-4">
<div className="flex items-center gap-2 text-sm">
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span>100% Natural Ingredients</span>
</div>
<div className="flex items-center gap-2 text-sm">
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span>No Side Effects</span>
</div>
<div className="flex items-center gap-2 text-sm">
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<span>Visible Results in 4-6 Weeks</span>
</div>
<div className="mb-8">
<StarRating rating={activeResult.rating} count={activeResult.reviewCount} />
</div>
<div className="mt-8">
{/* Benefits */}
<div className="space-y-3 mb-8">
{[
"Visible improvement in skin texture",
"Reduced appearance of fine lines",
"Improved skin hydration and radiance",
].map((benefit, index) => (
<div key={index} className="flex items-center gap-3">
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center flex-shrink-0">
<svg className="w-3.5 h-3.5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
</svg>
</div>
<span className="text-sm text-[#444444]">{benefit}</span>
</div>
))}
</div>
{/* CTA */}
<div className="flex flex-wrap gap-4">
<a
href="/products"
className="inline-block bg-black text-white px-8 py-4 text-sm uppercase tracking-[0.1em] font-medium hover:bg-black/90 transition-colors"
className="inline-block bg-black text-white px-8 py-4 text-sm uppercase tracking-[0.1em] font-medium hover:bg-[#333333] transition-colors"
>
Shop Now
</a>
<a
href="/reviews"
className="inline-block border-2 border-black text-black px-8 py-4 text-sm uppercase tracking-[0.1em] font-medium hover:bg-black hover:text-white transition-colors"
>
Read All Reviews
</a>
</div>
</motion.div>
</div>