Skip to main content

useSynchronizedAnimation Deep Dive

The useSynchronizedAnimation hook is designed to keep multiple CSS animations with the same name in sync across different components. It ensures that when a new component with a specific animation mounts, its animation starts at the same relative time as already running animations of the same name.


Core Concept

In complex UI layouts, you might have multiple elements using the same CSS animation (e.g., a pulsing effect or a rotating spinner). If these elements mount at different times, their animations will be out of phase. useSynchronizedAnimation solves this by:

  1. Tracking Current Time: It stashes the current playback time of the animation.
  2. Phase Matching: When a new element mounts, it applies the stashed time to the new animation.
  3. Global Synchronization: It uses document.getAnimations() to find all active animations and keep them aligned.

How it Works Step-by-Step

  1. Ref Creation: The hook creates a useRef that you must attach to the animated element.
  2. Animation Discovery: It uses the Web Animations API (document.getAnimations()) to find all animations matching the provided animationName.
  3. Target Matching: It identifies which specific animation from the list is attached to the component's ref.
  4. Synchronization Logic:
    • If this is the first instance of this animation mounting, and there is a stashedTime (from a previously unmounted instance), it resumes from that time.
    • If there are other instances already running, it syncs the current element's animation time to the time of the first discovered animation in the document.
  5. Unmount Cleanup: When the component unmounts, if it was the "lead" animation (the first one in the list), it stashes its currentTime so that subsequent mounts can resume from that point.

Example

import { useSynchronizedAnimation } from '@archibald/storefront';

const PulsingComponent = ({ label }) => {
// This hook ensures that ALL 'pulse-effect' animations
// across the entire app stay perfectly in sync.
const syncRef = useSynchronizedAnimation("pulse-effect");

return (
<div className="pulse-container" ref={syncRef}>
<span>{label}</span>
</div>
);
};

Note: This hook relies on the Web Animations API. If the browser does not support document.getAnimations, the hook will gracefully degrade and the animations will run independently.