ready to add animations
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
import { motion, useScroll, useSpring, useMotionValueEvent } from 'framer-motion';
|
||||
import { useRef, useState } from 'react';
|
||||
import { ReactNode, useRef } from 'react';
|
||||
|
||||
type ScrollLockedSectionProps = {
|
||||
id: string;
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
title: ReactNode;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const TAB_ITEMS = ['Inbox 24', 'Meetings 8', 'Subscriptions 2', 'Newsletters 6', 'Shopping 8'];
|
||||
|
||||
export const ScrollLockedSection = ({
|
||||
id,
|
||||
eyebrow,
|
||||
@@ -17,76 +14,34 @@ export const ScrollLockedSection = ({
|
||||
description,
|
||||
}: ScrollLockedSectionProps) => {
|
||||
const sectionRef = useRef<HTMLElement | null>(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: sectionRef,
|
||||
offset: ['start start', 'end end'],
|
||||
});
|
||||
const smoothProgress = useSpring(scrollYProgress, { stiffness: 120, damping: 30, mass: 0.4 });
|
||||
const [percent, setPercent] = useState(0);
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
|
||||
useMotionValueEvent(smoothProgress, 'change', (value) => {
|
||||
const percentage = Math.round(value * 100);
|
||||
setPercent(percentage);
|
||||
const nextIndex = Math.min(
|
||||
TAB_ITEMS.length - 1,
|
||||
Math.round(value * (TAB_ITEMS.length - 1)),
|
||||
);
|
||||
setActiveIndex(nextIndex);
|
||||
});
|
||||
|
||||
return (
|
||||
<section id={id} ref={sectionRef} className="relative h-[200vh] snap-start bg-[rgb(172,173,175)]">
|
||||
<section id={id} ref={sectionRef} className="relative h-[200vh] snap-start bg-black">
|
||||
<div className="sticky top-0 flex h-screen flex-col">
|
||||
<div className="mx-auto flex h-full w-full max-w-7xl flex-col justify-between px-6 py-24 sm:px-10 lg:px-20">
|
||||
<div className="space-y-6">
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.45em] text-ink/45">
|
||||
<div className="flex h-full w-full flex-col px-6 sm:px-10 lg:px-16">
|
||||
{/* Text Section - Takes ~20% of vertical space */}
|
||||
<div className="flex-shrink-0 space-y-4 pt-16 sm:pt-20 lg:pt-24">
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.45em] text-white">
|
||||
{eyebrow}
|
||||
</span>
|
||||
<div className="max-w-3xl space-y-3">
|
||||
<p className="text-3xl font-semibold leading-tight text-ink sm:text-[2.25rem] sm:leading-[1.2]">
|
||||
<p className="text-2xl font-semibold leading-tight text-white sm:text-3xl lg:text-[2.25rem] lg:leading-[1.2]">
|
||||
{title}
|
||||
</p>
|
||||
<p className="text-lg leading-relaxed text-ink/70">{description}</p>
|
||||
<p className="text-base leading-relaxed text-white/70 sm:text-lg">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-20 flex flex-1 flex-col justify-start">
|
||||
<div className="flex w-full flex-1 flex-col overflow-hidden rounded-[36px] border border-ink/10 bg-mist/70 shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] backdrop-blur">
|
||||
<div className="flex items-center justify-between px-10 pt-10 text-[11px] font-semibold uppercase tracking-[0.35em] text-ink/45">
|
||||
<span>Animation Placeholder</span>
|
||||
<motion.span initial={false} animate={{ opacity: percent > 0 ? 1 : 0.3 }}>
|
||||
{percent}%
|
||||
</motion.span>
|
||||
</div>
|
||||
<div className="flex-1 px-10 pb-12">
|
||||
<div className="flex h-full items-center justify-center rounded-[28px] border border-dashed border-ink/15 bg-white/50 text-xs font-semibold uppercase tracking-[0.4em] text-ink/25">
|
||||
Content Canvas
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-ink/10 bg-mist/80 px-8 py-6">
|
||||
<div className="flex items-center justify-between text-[11px] font-medium uppercase tracking-[0.3em] text-ink/35">
|
||||
{TAB_ITEMS.map((tab, index) => (
|
||||
<div key={tab} className="relative flex flex-1 justify-center">
|
||||
<span className={index === activeIndex ? 'text-ink' : 'text-ink/40'}>{tab}</span>
|
||||
<motion.span
|
||||
initial={false}
|
||||
animate={{ opacity: index === activeIndex ? 1 : 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeOut' }}
|
||||
className="absolute -bottom-3 left-1/2 h-1 w-16 -translate-x-1/2 rounded-full bg-ink"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-10 flex justify-center">
|
||||
{/* Animation Section - Takes ~80% of vertical space */}
|
||||
<div className="flex flex-col items-center gap-6 py-10 sm:gap-8 sm:py-12 lg:gap-10">
|
||||
<div className="mx-auto w-full border border-white/10 bg-black shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] aspect-[28/8]" />
|
||||
{/* Button below animation card */}
|
||||
<div className="flex justify-center">
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded-full border border-ink/15 bg-white/70 px-6 py-2 text-[11px] font-semibold uppercase tracking-[0.35em] text-ink/50 shadow-[0_16px_32px_-28px_rgba(0,0,0,0.65)] transition-colors duration-300 hover:border-ink/30 hover:text-ink/70"
|
||||
className="rounded-full border border-brand-200 bg-white px-5 py-2 text-sm font-semibold text-brand-700 shadow-subtle transition-all duration-300 hover:-translate-y-0.5 hover:border-brand-700 hover:bg-brand-700 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2 focus-visible:ring-offset-black"
|
||||
>
|
||||
Directory
|
||||
<span className="text-ink/30">Info</span>
|
||||
Directory Info
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user