buildmymcpserver/apps/web/components/scroll-cue.tsx
Marco Sadjadi 0cf9c66b6b
All checks were successful
Deploy to Production / deploy (push) Successful in 1m0s
feat(web): restore tall hero + carousel slide + viewport-fixed scroll cue
Three coordinated tweaks to the landing-page above-the-fold:

1. **Hero padding restored to py-14/sm:py-20/md:py-28** (was py-12/14/16).
   Compressing it for the scroll-cue position fight made the hero feel
   cramped and gave the ParticleHero background less room to breathe.
   With the cue moved out (see #3), there's no reason to shrink the hero.

2. **Step rotator switches to carousel-style horizontal slide.** The
   AnimatePresence transition was a fade+y-shift cross-fade — clean but
   sequential. Now the leaving card slides left out (x:-220) while the
   entering card slides right in (x:220→0), both coexisting in the same
   3D-space and inheriting the same mouse-tilt. The container gets
   `min-h-[240px]` so the absolutely-positioned cards have layout to
   anchor to (claude_desktop_config.json is the tallest at 7 lines).
   Reduced-motion still gets the opacity-only cross-fade — sliding
   content sideways is exactly the kind of motion that preference is
   meant to suppress.

3. **`<ScrollCue>` extracted into its own client component**, fixed-
   positioned at viewport bottom (bottom-5) with a frosted pill style.
   Fades to opacity:0 once `window.scrollY > 80`, so it doesn't shadow
   the rest of the page. Lives next to `<section>` in page.tsx rather
   than inside the hero — that way it anchors to the loadscreen's
   natural bottom edge whether the hero is short or tall.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 12:11:42 +02:00

44 lines
1.6 KiB
TypeScript

'use client';
import { ChevronDown } from 'lucide-react';
import { useEffect, useState } from 'react';
/**
* Scroll cue — a fixed pill anchored to the bottom of the viewport that
* points the visitor down to the flow video below the hero. Fades out
* once the user has scrolled past the loadscreen so it doesn't follow
* them around the page.
*
* Lives at z-30 so it sits above the hero content but below modals.
* The frosted pill (backdrop-blur + border) reads clearly against the
* particle background without stealing focus from the H1.
*/
export function ScrollCue({ targetId }: { targetId: string }) {
const [visible, setVisible] = useState(true);
useEffect(() => {
function onScroll() {
setVisible(window.scrollY < 80);
}
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
return (
<a
href={`#${targetId}`}
aria-label="See the flow in action"
className={`fixed inset-x-0 bottom-5 z-30 mx-auto flex w-fit items-center gap-1.5 rounded-full border border-[--color-border] px-3 py-1.5 text-[10.5px] uppercase tracking-[0.18em] text-[--color-fg-subtle] backdrop-blur transition-opacity duration-500 hover:text-[--color-fg] ${
visible ? 'opacity-100' : 'pointer-events-none opacity-0'
}`}
style={{
backgroundColor: 'color-mix(in oklab, var(--color-bg-elevated) 75%, transparent)',
}}
>
<span>see it run</span>
<ChevronDown size={12} className="animate-bounce" />
</a>
);
}