Skip to content

andreeich/gsap-react-queue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gsap-react-queue

A lightweight React utility for managing GSAP animation sequences in nested components. It addresses the common "React + GSAP timing trap" where child components' animations execute before the parent's due to React's bottom-up rendering and effect order. By using a shared context and queuing mechanism, this package ensures animations run in the desired sequence (e.g., parent first, then children) via a master timeline.

Installation

npm install gsap-react-queue

Or with Yarn:

yarn add gsap-react-queue

This package requires @gsap/react, gsap, and react as peer dependencies.

Example

Check out a working example on CodeSandbox: https://codesandbox.io/p/devbox/p4p7fp

The Problem It Solves

In React applications using GSAP with the useGSAP hook, animations in nested components often face a timing issue:

  • React's Rendering Order: React renders child components before completing the parent's render cycle. As a result, child effects (including useGSAP) run first.
  • Unexpected Animation Sequence: If you want a parent element to animate before its children (e.g., a container fading in, then its items sliding up), the children might start animating prematurely. This leads to visual glitches, overlapping tweens, or incorrect sequencing.
  • Common Scenarios: This "timing trap" appears in lists, modals, accordions, or any hierarchical UI where parent-child animation order matters. GSAP's timelines are powerful, but without coordination, nested useGSAP calls don't inherently respect a global order.
  • Why Not Just Pass Props?: While passing timelines via props works for simple cases, it becomes cumbersome in deeply nested or dynamic components (e.g., mapped lists). This package provides a declarative, hook-based queue that collects animations and executes them in sorted order on a shared timeline.

By wrapping your components in GSAPQueueProvider and using useGSAPQueue, animations are queued during the effect phase and executed sequentially after all components have mounted. You can override orders for fine control, ensuring parent → child flow without manual callbacks or refs propagation.

Usage

Basic Setup

Wrap your app or the relevant component tree with GSAPQueueProvider. This creates a shared timeline and queue.

import { GSAPQueueProvider } from 'gsap-react-queue';

function App() {
  return (
    <GSAPQueueProvider>
      <ParentComponent />
    </GSAPQueueProvider>
  );
}

Queuing Animations

In your components, use useGSAPQueue to add animations to the queue. The hook takes a function that receives gsap and the shared timeline, allowing you to add tweens in order.

  • Animations are auto-queued with incremental orders (0, 1, 2...).
  • Use orderOverride for explicit control (lower numbers execute first).

Parent Component Example

import { useGSAPQueue } from 'gsap-react-queue';
import { useRef } from 'react';

function ParentComponent() {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAPQueue((gsap, timeline) => {
    // Parent animation (order 0 by default)
    timeline.from(containerRef.current, { opacity: 0, duration: 1 });
  });

  return (
    <div ref={containerRef}>
      <ChildComponent />
    </div>
  );
}

Child Component Example

import { useGSAPQueue } from 'gsap-react-queue';
import { useRef } from 'react';

function ChildComponent() {
  const itemRef = useRef<HTMLDivElement>(null);

  useGSAPQueue((gsap, timeline) => {
    // Child animation (auto-assigned order 1)
    timeline.from(itemRef.current, { y: 50, opacity: 0, duration: 0.5 });
  });

  return <div ref={itemRef}>Child Content</div>;
}

In this setup:

  • The parent's fade-in starts first.
  • The child's slide-up follows sequentially on the same timeline.

Advanced: Custom Order and Cleanup

For explicit ordering or cleanup:

useGSAPQueue((gsap, timeline) => {
  timeline.to(someElement, { x: 100 });

  // Return a cleanup function if needed
  return () => {
    gsap.killTweensOf(someElement);
  };
}, 2); // orderOverride = 2 (executes after lower orders)

Using Context Directly

For more control, access the shared context:

import { useGSAPQueueContext } from 'gsap-react-queue';

function SomeComponent() {
  const { timeline, gsap, contextSafe } = useGSAPQueueContext();

  // Use timeline directly for complex logic
  timeline.to(...);
}

Props for Provider

  • gsap: Override the GSAP instance (defaults to imported gsap).
  • timeline: Provide a custom timeline (defaults to a new gsap.timeline()).

API

  • GSAPQueueProvider({ children, gsap?, timeline? }): Context provider for queuing.
  • useGSAPQueue(fn: (gsap, timeline) => void | (() => void), orderOverride?: number): Hook to queue an animation function.
  • useGSAPQueueContext(): Returns { queue, nextOrder, timeline, gsap, contextSafe } for direct access.

Contributing

See the repository for issues and pull requests.

License

MIT

About

Tools for orchestrating GSAP animations in React nested components, solving the timing trap where children animate before parents by queuing and sequencing with useGSAPQueue()

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors