ok
This commit is contained in:
BIN
public/.DS_Store
vendored
BIN
public/.DS_Store
vendored
Binary file not shown.
BIN
public/images/.DS_Store
vendored
BIN
public/images/.DS_Store
vendored
Binary file not shown.
@@ -7,6 +7,7 @@ import Team from '@/components/Team'
|
||||
import { Hero3 } from '@/components/Hero3'
|
||||
import { Hero4 } from '@/components/Hero4'
|
||||
import { Hero5 } from '@/components/Hero5'
|
||||
import StorySticky from '@/components/StorySticky'
|
||||
|
||||
|
||||
|
||||
@@ -15,10 +16,12 @@ export default function OurStory() {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero3 />
|
||||
<Hero4 />
|
||||
<Hero5 />
|
||||
<main className="bg-[#FEFFF6]">
|
||||
<StorySticky>
|
||||
<Hero3 />
|
||||
<Hero4 />
|
||||
<Hero5 />
|
||||
</StorySticky>
|
||||
<Team />
|
||||
</main>
|
||||
<Footer />
|
||||
|
@@ -6,33 +6,39 @@ import { ChevronDownIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
export function Hero3() {
|
||||
const scrollDown = () => {
|
||||
// Scroll to Hero4 (2nd section) - account for Hero3's 90vh height
|
||||
window.scrollTo({
|
||||
top: window.innerHeight * 0.9,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
const el = document.getElementById('section-2');
|
||||
if (!el) return;
|
||||
const offset = 88; // adjust if header differs
|
||||
const y = el.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top: y, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative w-full overflow-hidden mt-0">
|
||||
{/* Background Image - Extended to cover header */}
|
||||
<div
|
||||
id="section-1"
|
||||
data-story-section
|
||||
data-image="/images/hero_story1.jpg"
|
||||
className="relative w-full overflow-hidden mt-0"
|
||||
>
|
||||
{/* Background Image - stays for mobile, hidden on lg (sticky column takes over) */}
|
||||
<img
|
||||
src="/images/hero_story1.jpg"
|
||||
alt="Hero Story Background"
|
||||
className="w-full h-auto object-cover block relative z-0"
|
||||
className="w-full h-auto object-cover block relative z-0 lg:hidden"
|
||||
/>
|
||||
|
||||
{/* Black Overlay */}
|
||||
<div className="absolute inset-0 bg-black opacity-50"></div>
|
||||
{/* Black Overlay (mobile only) */}
|
||||
<div className="absolute inset-0 bg-black opacity-50 lg:hidden"></div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="absolute inset-0 lg:top-32 flex items-start justify-start text-start px-4 lg:px-8 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full">
|
||||
<H2 className="text-white">Our Story</H2>
|
||||
<P className="mt-4 text-white">THE TALE OF SACRED ENERGIES OF THE NILE</P>
|
||||
<PS className="mt-6 text-white">
|
||||
<div className="absolute inset-0 lg:static lg:inset-auto lg:top-0 flex items-start justify-start text-start px-4 lg:px-0 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full lg:pt-10">
|
||||
<H2 className=" ">Our Story</H2>
|
||||
<P className="mt-4 ">THE TALE OF SACRED ENERGIES OF THE NILE</P>
|
||||
<PS className="mt-6 ">
|
||||
Our founders, Isabelle Peeters and Kristof De Spiegeleer fell in love with the Nile and envisioned creating authentic, zen, art dahabeya to feel and experience in a unique way the mystical and the deep wisdom of the Nile.
|
||||
</PS>
|
||||
<PS className="mt-4 text-white">
|
||||
<PS className="mt-4 ">
|
||||
Their dream was to offer a sanctuary for the body, mind, and soul, a safe space to open yourself to new experiences, and allow the sacredness of the Nile to flow through you, to step back in the past, to align with the now helping you to reconnect with your true essence. A sanctuary for the body, mind, and soul, a safe space.
|
||||
</PS>
|
||||
|
||||
@@ -40,7 +46,7 @@ export function Hero3() {
|
||||
<div className="mt-8 flex justify-start">
|
||||
<ChevronDownIcon
|
||||
onClick={scrollDown}
|
||||
className="h-12 w-12 text-white animate-pulse cursor-pointer hover:text-gray-300 transition-colors duration-200"
|
||||
className="h-12 w-12 animate-pulse cursor-pointer hover:opacity-75 transition duration-200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -6,41 +6,41 @@ import { ChevronDownIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
export function Hero4() {
|
||||
const scrollDown = () => {
|
||||
// Scroll to Hero5 (3rd section) - account for Hero3 + Hero4 heights
|
||||
const hero3Height = window.innerHeight * 0.9; // Hero3 is 90vh
|
||||
const hero4Height = document.querySelector('img[src="/images/hero_story2.jpg"]')?.offsetHeight || window.innerHeight;
|
||||
window.scrollTo({
|
||||
top: hero3Height + hero4Height,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
const el = document.getElementById('section-3');
|
||||
if (!el) return;
|
||||
const offset = 88;
|
||||
const y = el.getBoundingClientRect().top + window.scrollY - offset;
|
||||
window.scrollTo({ top: y, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative w-full overflow-hidden mt-0">
|
||||
{/* Background Image - Extended to cover header */}
|
||||
<div
|
||||
id="section-2"
|
||||
data-story-section
|
||||
data-image="/images/hero_story2.jpg"
|
||||
className="relative w-full overflow-hidden mt-0"
|
||||
>
|
||||
<img
|
||||
src="/images/hero_story2.jpg"
|
||||
alt="Hero Story Background"
|
||||
className="w-full h-auto object-cover block relative z-0"
|
||||
className="w-full h-auto object-cover block relative z-0 lg:hidden"
|
||||
/>
|
||||
|
||||
{/* Black Overlay */}
|
||||
<div className="absolute inset-0 bg-black opacity-50"></div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="absolute inset-0 lg:top-32 flex items-start justify-start text-start px-4 lg:px-8 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full">
|
||||
<PS className=" text-white">
|
||||
|
||||
<div className="absolute inset-0 bg-black opacity-50 lg:hidden"></div>
|
||||
|
||||
<div className="absolute inset-0 lg:static lg:inset-auto lg:top-0 flex items-start justify-start text-start px-4 lg:px-0 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full lg:pt-10">
|
||||
<PS className=" ">
|
||||
We are unique in the market as the cruises are designed to provide for a private, personalised and wellness experience on the River Nile. Families, communities or dedicated groups up to sixty people can sail the Nile together discovering her hidden treasures. The Nile is a powerful natural energy source, and the boats are designed to help you align with its frequencies to feel the magic carried by sacred waters of the Nile.
|
||||
</PS>
|
||||
<PS className="mt-6 text-white">
|
||||
<PS className="mt-6 ">
|
||||
Frequencies are the new currency. Our mission is to help you recognize and align with different frequencies, creating a deeply fulfilling life in tune with your soul's gifts. Self-knowledge and self-mastery are the keys to fully opening your heart. By understanding and resonating with these frequencies, you can achieve a life of harmony and fulfillment.
|
||||
</PS>
|
||||
|
||||
{/* Chevron Down Button */}
|
||||
|
||||
<div className="mt-8 flex justify-start">
|
||||
<ChevronDownIcon
|
||||
<ChevronDownIcon
|
||||
onClick={scrollDown}
|
||||
className="h-12 w-12 text-white animate-pulse cursor-pointer hover:text-gray-300 transition-colors duration-200"
|
||||
className="h-12 w-12 animate-pulse cursor-pointer hover:opacity-75 transition duration-200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -7,30 +7,32 @@ import { ChevronUpIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
export function Hero5() {
|
||||
return (
|
||||
<div className="relative w-full overflow-hidden mt-0">
|
||||
{/* Background Image - Extended to cover header */}
|
||||
<div
|
||||
id="section-3"
|
||||
data-story-section
|
||||
data-image="/images/hero_story3.jpg"
|
||||
className="relative w-full overflow-hidden mt-0"
|
||||
>
|
||||
<img
|
||||
src="/images/hero_story3.jpg"
|
||||
alt="Hero Story Background"
|
||||
className="w-full h-auto object-cover block relative z-0"
|
||||
className="w-full h-auto object-cover block relative z-0 lg:hidden"
|
||||
/>
|
||||
|
||||
{/* Black Overlay */}
|
||||
<div className="absolute inset-0 bg-black opacity-50"></div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="absolute inset-0 lg:top-32 flex items-start justify-start text-start px-4 lg:px-8 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full">
|
||||
<PS className=" text-white">
|
||||
|
||||
<div className="absolute inset-0 bg-black opacity-50 lg:hidden"></div>
|
||||
|
||||
<div className="absolute inset-0 lg:static lg:inset-auto lg:top-0 flex items-start justify-start text-start px-4 lg:px-0 z-20">
|
||||
<div className="max-w-xs sm:max-w-md md:max-w-2xl lg:max-w-2xl w-full lg:pt-10">
|
||||
<PS className=" ">
|
||||
Are you ready to step out of your comfort zone and embrace these changes? Can you let the new energies flow through you and break free from outdated programs to welcome new wisdom?
|
||||
</PS>
|
||||
<PS className="mt-6 text-white">
|
||||
<PS className="mt-6 ">
|
||||
Together, let us open new gates of consciousness and expand the flow of unconditional love. The magical energy of the Nile is ready to flow through us, uniting us in a heartbeat. Home is calling you, inviting you to a journey of inner discovery and profound connection.
|
||||
</PS>
|
||||
<H4 className="text-base mt-8 font-semibold leading-7 italic text-gold-600">With Love,</H4>
|
||||
<H4 className="text-base font-semibold leading-7 text-white">Kristof & Isabelle</H4>
|
||||
</div>
|
||||
<H4 className="text-base mt-8 font-semibold leading-7 italic text-gold-600">With Love,</H4>
|
||||
<H4 className="text-base font-semibold leading-7 ">Kristof & Isabelle</H4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@@ -17,9 +17,9 @@ const SvgIcon = (props) => (
|
||||
maskUnits="userSpaceOnUse"
|
||||
style={{ maskType: "luminance" }}
|
||||
>
|
||||
<path fill="#ffffff" d="M29.926 0H0v30h29.926z"></path>
|
||||
<path fill="#48774B" d="M29.926 0H0v30h29.926z"></path>
|
||||
</mask>
|
||||
<g fill="#ffffff" fillOpacity="0.7" mask="url(#a)">
|
||||
<g fill="#48774B" fillOpacity="0.8" mask="url(#a)">
|
||||
<path d="M14.963 15c4.132 0 7.482-3.358 7.482-7.5S19.095 0 14.963 0 7.481 3.358 7.481 7.5s3.35 7.5 7.482 7.5"></path>
|
||||
<path d="M7.482 22.5c4.132 0 7.481-3.358 7.481-7.5s-3.35-7.5-7.481-7.5S0 10.858 0 15s3.35 7.5 7.482 7.5"></path>
|
||||
<path d="M22.444 22.5c4.132 0 7.482-3.358 7.482-7.5s-3.35-7.5-7.482-7.5-7.481 3.358-7.481 7.5 3.35 7.5 7.481 7.5"></path>
|
||||
@@ -29,7 +29,7 @@ const SvgIcon = (props) => (
|
||||
<path d="M9.673 17.197c4.132 0 7.481-3.358 7.481-7.5s-3.35-7.5-7.481-7.5-7.482 3.358-7.482 7.5 3.35 7.5 7.482 7.5"></path>
|
||||
<path d="M20.253 17.197c4.132 0 7.482-3.358 7.482-7.5s-3.35-7.5-7.482-7.5-7.482 3.358-7.482 7.5 3.35 7.5 7.482 7.5"></path>
|
||||
</g> <path
|
||||
fill="#ffffff"
|
||||
fill="#48774B"
|
||||
d="m47.525 24-7.65-17.5H43.4l6.825 15.825H48.2L55.1 6.5h3.25L50.725 24zm18.196-10.225h8.7v2.675h-8.7zm.25 7.5h9.875V24H62.721V6.5h12.775v2.725h-9.525zM81.97 24V6.5h7.65q2.85 0 5 1.1t3.35 3.05 1.2 4.6q0 2.625-1.2 4.6-1.2 1.95-3.35 3.05t-5 1.1zm3.25-2.75h4.25q1.975 0 3.4-.75 1.45-.75 2.225-2.1.8-1.35.8-3.15 0-1.826-.8-3.15-.774-1.35-2.225-2.1-1.425-.75-3.4-.75h-4.25zM102.404 24l7.875-17.5h3.2l7.9 17.5h-3.4l-6.775-15.775h1.3L105.754 24zm3.625-4.05.875-2.55h9.45l.875 2.55z"
|
||||
></path>
|
||||
</svg>
|
||||
|
99
src/components/StorySticky.jsx
Normal file
99
src/components/StorySticky.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
export default function StorySticky({ children }) {
|
||||
const [sections, setSections] = useState([]);
|
||||
const [activeIdx, setActiveIdx] = useState(0);
|
||||
const containerRef = useRef(null);
|
||||
|
||||
const prefersReducedMotion = useMemo(
|
||||
() =>
|
||||
typeof window !== 'undefined' &&
|
||||
window.matchMedia?.('(prefers-reduced-motion: reduce)').matches,
|
||||
[]
|
||||
);
|
||||
|
||||
// Collect sections from children after mount
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
const nodes = Array.from(
|
||||
containerRef.current.querySelectorAll('[data-story-section]')
|
||||
);
|
||||
|
||||
const list = nodes.map((el, i) => ({
|
||||
id: el.id || `section-${i + 1}`,
|
||||
image: el.dataset.image || '',
|
||||
el,
|
||||
}));
|
||||
setSections(list);
|
||||
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const visible = entries
|
||||
.filter((e) => e.isIntersecting)
|
||||
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
|
||||
if (!visible) return;
|
||||
const idx = list.findIndex((s) => s.el === visible.target);
|
||||
if (idx >= 0) setActiveIdx(idx);
|
||||
},
|
||||
{
|
||||
root: null,
|
||||
threshold: [0.3, 0.6, 0.9],
|
||||
rootMargin: '0px 0px -30% 0px',
|
||||
}
|
||||
);
|
||||
|
||||
nodes.forEach((n) => io.observe(n));
|
||||
return () => io.disconnect();
|
||||
}, [children]);
|
||||
|
||||
return (
|
||||
<section className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-0 lg:py-12">
|
||||
{/* Mobile: render as-is */}
|
||||
<div className="lg:hidden">{children}</div>
|
||||
|
||||
{/* Desktop: 2-col layout with sticky media */}
|
||||
<div className="hidden lg:grid lg:grid-cols-12 lg:gap-8" ref={containerRef}>
|
||||
{/* Sticky left media */}
|
||||
<div className="relative lg:col-span-6">
|
||||
<div className="sticky top-28 h-[75vh] rounded-2xl overflow-hidden shadow-lg">
|
||||
<div className="absolute inset-0">
|
||||
{sections.map((s, i) => (
|
||||
<div
|
||||
key={s.id}
|
||||
className={[
|
||||
'absolute inset-0 transition-opacity duration-700',
|
||||
i === activeIdx ? 'opacity-100' : 'opacity-0',
|
||||
].join(' ')}
|
||||
style={prefersReducedMotion ? { transitionDuration: '0ms' } : undefined}
|
||||
aria-hidden={i !== activeIdx}
|
||||
>
|
||||
{s.image ? (
|
||||
<Image
|
||||
src={s.image}
|
||||
alt=""
|
||||
fill
|
||||
sizes="50vw"
|
||||
priority={i === 0}
|
||||
className="object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-neutral-200" />
|
||||
)}
|
||||
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/25 via-transparent to-transparent" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right column = the original heroes (but with their own media hidden via lg:hidden) */}
|
||||
<div className="lg:col-span-6 flex flex-col gap-24">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user