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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user