feat: add portrait with parallax, real product cards, and testimonial avatars to Home

This commit is contained in:
belviskhoremk
2026-08-03 22:59:25 +00:00
parent c690c8292a
commit 726893ab87
3 changed files with 71 additions and 15 deletions

View File

@@ -24,7 +24,7 @@
}
.section {
padding: var(--space-xl) var(--space-lg);
padding: var(--space-lg) var(--space-lg);
text-align: center;
}
@@ -41,6 +41,45 @@
margin-top: var(--space-lg);
}
.aboutGrid {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-xl);
flex-wrap: wrap;
text-align: left;
max-width: 800px;
margin: 0 auto;
}
.aboutGrid h2,
.aboutGrid p {
text-align: left;
}
.portrait {
width: 220px;
height: 220px;
object-fit: cover;
border-radius: 8px;
flex-shrink: 0;
}
.testimonial {
display: flex;
flex-direction: column;
align-items: center;
max-width: 260px;
}
.avatar {
width: 56px;
height: 56px;
border-radius: 50%;
object-fit: cover;
margin-bottom: var(--space-sm);
}
.banner {
background: var(--color-charcoal);
color: var(--color-cream);

View File

@@ -37,4 +37,9 @@ describe('Home page', () => {
await userEvent.click(screen.getByRole('button', { name: new RegExp(services[0].name) }))
expect(screen.getByLabelText(/choose a date/i)).toBeInTheDocument()
})
it('renders the About Mira portrait', () => {
renderHome()
expect(screen.getByRole('img', { name: /mira/i })).toBeInTheDocument()
})
})

View File

@@ -1,19 +1,23 @@
import { Link, useNavigate } from 'react-router-dom'
import { motion, useScroll, useTransform } from 'framer-motion'
import Hero3DScene from '../components/Hero3DScene'
import ScrollReveal from '../components/ScrollReveal'
import ServiceCard from '../components/ServiceCard'
import ProductCard from '../components/ProductCard'
import { services } from '../data/services'
import { products } from '../data/products'
import styles from './Home.module.css'
const TESTIMONIALS = [
{ quote: 'Mira made me feel like royalty in her chair. My braids lasted 8 weeks!', author: 'Amara T.' },
{ quote: 'The most gentle, precise braider I have ever been to.', author: 'Keisha R.' },
{ quote: 'Booking was so easy and the results speak for themselves.', author: 'Nadia F.' },
{ quote: 'Mira made me feel like royalty in her chair. My braids lasted 8 weeks!', author: 'Amara T.', avatar: '/testimonials/amara.jpg' },
{ quote: 'The most gentle, precise braider I have ever been to.', author: 'Keisha R.', avatar: '/testimonials/keisha.jpg' },
{ quote: 'Booking was so easy and the results speak for themselves.', author: 'Nadia F.', avatar: '/testimonials/nadia.jpg' },
]
function Home() {
const navigate = useNavigate()
const { scrollYProgress } = useScroll()
const portraitY = useTransform(scrollYProgress, [0, 1], [0, -40])
return (
<div>
@@ -29,12 +33,22 @@ function Home() {
<ScrollReveal>
<section className={styles.altSection}>
<h2>About Mira</h2>
<p>
With over a decade behind the chair, Mira treats every install as an art form —
gentle on the scalp, precise at the root, and finished with a crown you'll want
to show off.
</p>
<div className={styles.aboutGrid}>
<motion.img
src="/about/mira-portrait.jpg"
alt="Mira, owner and stylist at Braids by Mira"
className={styles.portrait}
style={{ y: portraitY }}
/>
<div>
<h2>About Mira</h2>
<p>
With over a decade behind the chair, Mira treats every install as an art form —
gentle on the scalp, precise at the root, and finished with a crown you'll want
to show off.
</p>
</div>
</div>
</section>
</ScrollReveal>
@@ -58,10 +72,7 @@ function Home() {
<h2>Shop Highlights</h2>
<div className={styles.row}>
{products.filter((p) => p.inStock).slice(0, 3).map((product) => (
<div key={product.id}>
<p>{product.name}</p>
<p>${product.price}</p>
</div>
<ProductCard key={product.id} product={product} onInquire={() => navigate('/shop')} />
))}
</div>
<p><Link to="/shop">Shop All</Link></p>
@@ -73,7 +84,8 @@ function Home() {
<h2>Client Love</h2>
<div className={styles.row}>
{TESTIMONIALS.map((t) => (
<blockquote key={t.author}>
<blockquote key={t.author} className={styles.testimonial}>
<img src={t.avatar} alt={t.author} className={styles.avatar} />
<p>&ldquo;{t.quote}&rdquo;</p>
<cite>{t.author}</cite>
</blockquote>