feat: remove scroll indicator, add auto-scroll from hero to next section

- Remove SCROLL chevron button from hero (not needed)
- Add wheel/swipe listener that smoothly scrolls to the first section below hero
- Works on desktop (wheel) and mobile (touch swipe)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 14:08:30 +03:00
parent 66dce3f8f5
commit e63b902081

View File

@@ -1,9 +1,9 @@
"use client";
import { useEffect, useRef, useCallback } from "react";
import { Button } from "@/components/ui/Button";
import { FloatingHearts } from "@/components/ui/FloatingHearts";
import { HeroLogo } from "@/components/ui/HeroLogo";
import { ChevronDown } from "lucide-react";
import type { SiteContent } from "@/types/content";
interface HeroProps {
@@ -11,9 +11,65 @@ interface HeroProps {
}
export function Hero({ data: hero }: HeroProps) {
const sectionRef = useRef<HTMLElement>(null);
const scrolledRef = useRef(false);
const scrollToNext = useCallback(() => {
const hero = sectionRef.current;
if (!hero) return;
// Find the next sibling section
let next = hero.nextElementSibling;
while (next && next.tagName !== "SECTION") {
next = next.nextElementSibling;
}
next?.scrollIntoView({ behavior: "smooth" });
}, []);
useEffect(() => {
const hero = sectionRef.current;
if (!hero) return;
function handleWheel(e: WheelEvent) {
// Only trigger when scrolling down and still inside hero
if (e.deltaY <= 0 || scrolledRef.current) return;
if (window.scrollY > 10) return; // already scrolled past hero top
scrolledRef.current = true;
scrollToNext();
// Reset after animation completes
setTimeout(() => { scrolledRef.current = false; }, 1000);
}
function handleTouchStart(e: TouchEvent) {
(hero as HTMLElement).dataset.touchY = String(e.touches[0].clientY);
}
function handleTouchEnd(e: TouchEvent) {
const startY = Number((hero as HTMLElement).dataset.touchY);
const endY = e.changedTouches[0].clientY;
const diff = startY - endY;
// Swipe down (finger moves up) with enough distance
if (diff > 50 && !scrolledRef.current && window.scrollY < 10) {
scrolledRef.current = true;
scrollToNext();
setTimeout(() => { scrolledRef.current = false; }, 1000);
}
}
hero.addEventListener("wheel", handleWheel, { passive: true });
hero.addEventListener("touchstart", handleTouchStart, { passive: true });
hero.addEventListener("touchend", handleTouchEnd, { passive: true });
return () => {
hero.removeEventListener("wheel", handleWheel);
hero.removeEventListener("touchstart", handleTouchStart);
hero.removeEventListener("touchend", handleTouchEnd);
};
}, [scrollToNext]);
return (
<section className="relative flex min-h-svh items-center justify-center overflow-hidden bg-[#050505]">
<section ref={sectionRef} className="relative flex min-h-svh items-center justify-center overflow-hidden bg-[#050505]">
{/* Animated gradient background */}
<div className="hero-bg-gradient absolute inset-0" />
@@ -72,16 +128,6 @@ export function Hero({ data: hero }: HeroProps) {
</div>
</div>
{/* Scroll indicator */}
<div className="hero-cta absolute bottom-8 left-1/2 -translate-x-1/2">
<a
href="#about"
className="flex flex-col items-center gap-1 text-neutral-600 transition-colors hover:text-gold-light"
>
<span className="text-xs uppercase tracking-widest">Scroll</span>
<ChevronDown size={20} className="animate-bounce" />
</a>
</div>
</section>
);
}