first publish
This commit is contained in:
commit
b8e41b4d55
147 files changed
+19367
No files matched your search
@@ -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;
|
||||
Reference in new issue
Block a user