UNPKG

reactbits-mcp-server

Version:

MCP Server for React Bits - Access 99+ React components with animations, backgrounds, and UI elements

91 lines (81 loc) 2.01 kB
import { useEffect, useMemo, useRef } from "react"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; gsap.registerPlugin(ScrollTrigger); const ScrollFloat = ({ children, scrollContainerRef, containerClassName = "", textClassName = "", animationDuration = 1, ease = "back.inOut(2)", scrollStart = "center bottom+=50%", scrollEnd = "bottom bottom-=40%", stagger = 0.03 }) => { const containerRef = useRef(null); const splitText = useMemo(() => { const text = typeof children === "string" ? children : ""; return text.split("").map((char, index) => ( <span className="inline-block word" key={index}> {char === " " ? "\u00A0" : char} </span> )); }, [children]); useEffect(() => { const el = containerRef.current; if (!el) return; const scroller = scrollContainerRef && scrollContainerRef.current ? scrollContainerRef.current : window; const charElements = el.querySelectorAll(".inline-block"); gsap.fromTo( charElements, { willChange: "opacity, transform", opacity: 0, yPercent: 120, scaleY: 2.3, scaleX: 0.7, transformOrigin: "50% 0%" }, { duration: animationDuration, ease: ease, opacity: 1, yPercent: 0, scaleY: 1, scaleX: 1, stagger: stagger, scrollTrigger: { trigger: el, scroller, start: scrollStart, end: scrollEnd, scrub: true }, } ); }, [ scrollContainerRef, animationDuration, ease, scrollStart, scrollEnd, stagger ]); return ( <h2 ref={containerRef} className={`my-5 overflow-hidden ${containerClassName}`} > <span className={`inline-block text-[clamp(1.6rem,4vw,3rem)] leading-[1.5] ${textClassName}`} > {splitText} </span> </h2> ); }; export default ScrollFloat;