npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-air-transition

v1.0.0

Published

React enter/exit animations with anime.js and react-transition-group

Readme

react-air-transition

A thin React wrapper around react-transition-group and anime.js v4 for enter/exit animations.

  • react-transition-group — mounts/unmounts the child and runs enter/exit lifecycle hooks (onEntering, onExiting, …).
  • anime.js — drives the actual CSS/transform animations via animate().

You configure transitions declaratively; the wrapper wires both libraries together so you do not have to call them manually.

Bundle size (wrapper only): ~1.44 kB gzip (~3.8 kB minified).

Features

  • Declarative show/hide via the active prop
  • Custom enter/exit animations (opacity, transforms, height, and any anime.js-supported properties)
  • Interrupt handling: switching active mid-animation reverses smoothly
  • height: auto support for expand/collapse patterns
  • Staggered lists via enterDelay + delayIndex
  • In-place updates on mounted elements via the animation prop
  • TypeScript types included

Installation

npm install react-air-transition

Peer dependency: React 19+

animejs and react-transition-group are installed automatically as dependencies of this package.

Quick start

import { useState } from 'react';
import { AirTransition } from 'react-air-transition';

function App() {
  const [visible, setVisible] = useState(true);

  return (
    <>
      <button onClick={() => setVisible((v) => !v)}>Toggle</button>

      <AirTransition
        active={visible}
        duration={400}
        enter={{opacity: [0, 1], translateY: ['16px', '0px']}}
        exit={{opacity: 0, translateY: '16px'}}
      >
        <div>Animated content</div>
      </AirTransition>
    </>
  );
}

Ref requirement

children must be a single React element that can receive a ref (native DOM element or forwardRef component). If your component cannot take a ref, wrap it in a <div> (or another DOM element).

API

AirTransition

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | ReactElement | — | Element to animate (must accept ref) | | active | boolean | — | When true, the element is shown; when false, it is hidden | | enter | TransitionDescription \| null | {opacity: [0, 1]} | Enter animation. null disables enter animation | | exit | TransitionDescription \| null | {opacity: 0} | Exit animation. null disables exit animation | | duration | number | 300 | Duration in ms; overridden by duration inside enter / exit / animation | | enterEase | EasingParam | 'outCubic' | Easing for enter (anime.js v4) | | exitEase | EasingParam | 'outCubic' | Easing for exit | | enterDelay | number | — | Base delay before enter; multiplied by delayIndex | | exitDelay | number | — | Base delay before exit; multiplied by delayIndex | | delayIndex | number | 1 | Multiplier for staggered lists (delay * delayIndex) | | animateOnMount | boolean | false | Run enter animation on first mount | | animateOnUnmount | boolean | true | Run exit animation before unmount; false skips exit animation | | removeStylesOnEnter | boolean | false | Remove inline styles applied during enter after it completes | | animation | TransitionDescription | — | Animate an already-mounted element when this object changes |

Additional props are forwarded to the underlying Transition from react-transition-group.

TransitionDescription

Animation config compatible with anime.js v4 animate(). Common fields:

| Field | Type | Description | |-------|------|-------------| | duration | number | Duration in ms | | delay | number | Delay in ms | | ease | EasingParam | Easing function name or custom easing | | * | string \| number \| Array | Any animatable CSS/transform property. Use [from, to] on enter; on exit, prefer a single target value (anime.js animates from the current state) |

Example (enter + exit):

// enter — explicit from → to
enter: {
  opacity: [0, 1],
  translateY: ['20px', '0px'],
  duration: 500,
  ease: 'outQuad',
}

// exit — target values only
exit: {
  opacity: 0,
  translateY: '20px',
}

Examples

Fade and slide

<AirTransition
  active={open}
  duration={400}
  enter={{opacity: [0, 1], translateY: ['16px', '0px']}}
  exit={{opacity: 0, translateY: '16px'}}
>
  <div>Content</div>
</AirTransition>

Collapsible panel (height: auto)

<AirTransition
  active={expanded}
  duration={350}
  enter={{height: [0, 'auto'], opacity: [0, 1]}}
  exit={{height: 0, opacity: 0}}
  enterEase="outQuad"
  exitEase="inQuad"
>
  <div style={{overflow: 'hidden'}}>Expandable section</div>
</AirTransition>

auto is resolved to the element’s scrollHeight at animation time.

Staggered list

{items.map((item, index) => (
  <AirTransition
    key={item.id}
    active={showList}
    enterDelay={80}
    delayIndex={index + 1}
    duration={300}
    enter={{opacity: [0, 1], translateX: ['-12px', '0px']}}
    exit={{opacity: 0, translateX: '-12px'}}
  >
    <div>{item.label}</div>
  </AirTransition>
))}

In-place animation (mounted element)

Use when the element stays mounted and you only want to animate property changes:

<AirTransition
  active
  animation={
    shifted
      ? {translateX: '48px'}
      : {translateX: '0px'}
  }
>
  <div>Slides without unmounting</div>
</AirTransition>

Behavior notes

  • Unmount: The component uses unmountOnExit — when active is false, the child is removed from the DOM after the exit animation (unless exit is null or animateOnUnmount is false).
  • Interrupted animations: If enter starts during exit (or vice versa), the running animation is cancelled and the new one continues from the current visual state.

License

MIT