// flow-scroll.jsx — FlowArt stacking scroll effect (GSAP + ScrollTrigger)
// GSAP + ScrollTrigger must be loaded via CDN before this file runs
gsap.registerPlugin(ScrollTrigger);
const FlowSection = ({ children, id, ariaLabel, bg }) => (
);
const FlowArt = ({ children }) => {
const ref = React.useRef(null);
React.useEffect(() => {
const el = ref.current;
if (!el) return;
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const sections = Array.from(el.querySelectorAll('[data-flow-section]'));
if (!sections.length) return;
const triggers = [];
sections.forEach((section, i) => {
gsap.set(section, { zIndex: i + 1 });
const inner = section.querySelector('.flow-art-container');
if (!inner) return;
if (i > 0) {
gsap.set(inner, { rotation: 30, transformOrigin: 'bottom left' });
const tween = gsap.to(inner, {
rotation: 0,
ease: 'none',
scrollTrigger: {
trigger: section,
start: 'top bottom',
end: 'top 25%',
scrub: true,
},
});
if (tween.scrollTrigger) triggers.push(tween.scrollTrigger);
}
if (i < sections.length - 1) {
triggers.push(
ScrollTrigger.create({
trigger: section,
start: 'bottom bottom',
end: 'bottom top',
pin: true,
pinSpacing: false,
})
);
}
});
ScrollTrigger.refresh();
return () => {
triggers.forEach(t => t.kill());
ScrollTrigger.refresh();
};
}, []);
return (
{children}
);
};
Object.assign(window, { FlowArt, FlowSection });