first publish

This commit is contained in:
knso committed 2026-09-06 17:21:52 +02:00
commit b8e41b4d55
147 files changed
+19367

No files matched your search

+43
View File
@@ -0,0 +1,43 @@
"use client";
import { useLayoutEffect, useRef } from "react";
import { gsap, EASE, MM } from "@/lib/gsap";
/**
* 1 px `--accent` line directly under the header (the header writes
* `--header-h` on <html>). Grows with the page scroll; purely decorative.
*
* Scrubbed by ScrollTrigger, not by a second animation runtime: this was the
* only reason `useScroll` (framer-motion) shipped on every route.
*/
export function ScrollProgress() {
const bar = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
const el = bar.current;
if (!el) return;
const mm = gsap.matchMedia();
mm.add({ reduce: MM.reduce, ok: MM.ok }, () => {
/* Reduced motion too: the bar reports position, it does not animate for effect –
the scrub follows the reader's own scrolling either way. */
gsap.set(el, { scaleX: 0, transformOrigin: "0 50%" });
gsap.to(el, {
scaleX: 1,
ease: EASE.none,
scrollTrigger: { trigger: document.documentElement, start: "top top", end: "bottom bottom", scrub: true },
});
});
return () => mm.revert();
}, []);
return (
<div
ref={bar}
aria-hidden="true"
className="pointer-events-none fixed inset-x-0 z-50 h-px origin-left scale-x-0 bg-accent transition-opacity duration-300 [[data-menu-open]_&]:opacity-0"
style={{ top: "var(--header-h, 60px)" }}
/>
);
}
export default ScrollProgress;