diff --git a/src/App.tsx b/src/App.tsx index 5c16f8e..76bb019 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { APPS } from "./data/apps"; import { CATEGORY_LABELS, @@ -27,8 +27,38 @@ import { FooterCta } from "./components/footer-cta"; import { Card } from "./components/ui/card"; import { assetPath } from "./lib/assets"; +// Track scroll progress from 0 to 1 over a given pixel distance +// Uses requestAnimationFrame to avoid jank +function useScrollProgress(thresholdPx = 200) { + const [progress, setProgress] = useState(0); + const tickingRef = useRef(false); + + const handler = useCallback(() => { + if (tickingRef.current) return; + tickingRef.current = true; + requestAnimationFrame(() => { + const scrollY = window.scrollY || document.documentElement.scrollTop; + setProgress(Math.min(1, Math.max(0, scrollY / thresholdPx))); + tickingRef.current = false; + }); + }, [thresholdPx]); + + useEffect(() => { + window.addEventListener("scroll", handler, { passive: true }); + return () => window.removeEventListener("scroll", handler); + }, [handler]); + + return progress; +} + +/** Interpolate between two values based on progress (0..1) */ +function lerp(a: number, b: number, t: number): number { + return a + (b - a) * t; +} + function App() { const [filters, setFilters] = useState(() => parseFiltersFromSearch(window.location.search)); + const scrollProgress = useScrollProgress(); useEffect(() => { document.title = "Bitcoin Apps Directory"; @@ -52,17 +82,59 @@ function App() { const searching = filters.q.trim().length > 0; + // --- Collapsible header state --- + const isCollapsed = scrollProgress >= 0.95; + const bannerOpacity = Math.max(0, 1 - scrollProgress * 2.5); + const titleScale = lerp(1, 0.65, scrollProgress); + const subtitleFade = Math.max(0, 1 - scrollProgress * 2); + const titleYOffset = lerp(0, 8, scrollProgress); + return (
-
-
- Discover apps banner + {/* Collapsible hero section */} +
+ {/* Banner image - fades out first */} +
+ Discover apps banner
+ + {/* Title + subtitle */}
-

+

Bitcoin Apps Directory

-

+

A collection of apps, websites and services
to connect your bitcoin wallet to.