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 🙏

© 2025 – Pkg Stats / Ryan Hefner

rani-motion

v1.0.2

Published

A simple and powerful React animation library with TypeScript support - animated.div style components with accessibility-first approach

Downloads

7

Readme

Rani

A simple and powerful React animation library with TypeScript support, presets, and custom animations.

Installation

npm install rani-motion
# or
yarn add rani-motion

Quick Start

Method 1: Using animated.div (Recommended)

import { animated } from 'rani-motion';

function App() {
  return (
    <div>
      {/* Basic scroll-triggered animation */}
      <animated.div animation="fadeInUp" duration={800}>
        <h1>This will fade in from bottom when scrolled into view</h1>
      </animated.div>

      {/* Different HTML elements */}
      <animated.section animation="slideInLeft" delay={200}>
        <p>This section slides in from left with a delay</p>
      </animated.section>

      <animated.h1 animation="bounceIn" duration={1000}>
        Bouncing Heading!
      </animated.h1>

      <animated.button 
        animation="scaleIn"
        onClick={() => console.log('Clicked!')}
      >
        Interactive Button
      </animated.button>
    </div>
  );
}

Method 2: Using Component Wrappers

import { RaniOnView, RaniHover, RaniClick } from 'rani-motion';

function App() {
  return (
    <div>
      {/* Basic scroll-triggered animation */}
      <RaniOnView animation="fadeInUp" duration={800}>
        <div>This will fade in from bottom when scrolled into view</div>
      </RaniOnView>

      {/* Hover animation */}
      <RaniHover animation="scale">
        <button>Hover me!</button>
      </RaniHover>

      {/* Click animation */}
      <RaniClick animation="ripple">
        <button>Click for ripple effect</button>
      </RaniClick>
    </div>
  );
}

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import { 
  RaniOnView, 
  AnimationPreset, 
  CustomAnimation 
} from 'rani-motion';

const customAnim: CustomAnimation = {
  initial: { opacity: 0, transform: 'scale(0.8)' },
  animate: { opacity: 1, transform: 'scale(1)' }
};

const MyComponent: React.FC = () => {
  return (
    <RaniOnView 
      animation="fadeInUp" // Type-safe preset names
      customAnimation={customAnim} // Type-safe custom animations
    >
      <div>Fully typed animations!</div>
    </RaniOnView>
  );
};

Available Animations

Scroll Animations (RaniOnView / animated.*)

  • Fade: fadeIn, fadeInUp, fadeInDown, fadeInLeft, fadeInRight
  • Slide: slideInUp, slideInDown, slideInLeft, slideInRight
  • Scale: scaleIn, scaleInUp, zoomIn
  • Rotate: rotateIn, rotateInLeft, rotateInRight
  • Bounce: bounceIn, bounceInUp
  • Flip: flipInX, flipInY
  • Special: lightSpeedIn, rollIn

Hover Animations (RaniHover)

  • scale, scaleDown, lift, rotate, skew, glow, bounce, wobble

Click Animations (RaniClick)

  • pulse, ripple, shake

Advanced Usage

Animated HTML Elements

The animated object provides animated versions of common HTML elements:

import { animated } from 'rani-motion';

// All these elements support the same animation props
<animated.div animation="fadeInUp" duration={600} />
<animated.span animation="slideInLeft" delay={200} />
<animated.section animation="bounceIn" />
<animated.article animation="rotateIn" />
<animated.header animation="fadeInDown" />
<animated.footer animation="slideInUp" />
<animated.main animation="zoomIn" />
<animated.nav animation="fadeInRight" />
<animated.h1 animation="scaleIn" />
<animated.h2 animation="flipInX" />
<animated.h3 animation="lightSpeedIn" />
<animated.p animation="rollIn" />
<animated.a animation="fadeIn" />
<animated.button animation="bounceInUp" />
<animated.img animation="fadeInLeft" />
<animated.ul animation="slideInDown" />
<animated.ol animation="slideInRight" />
<animated.li animation="fadeInUp" />

Custom Animations with TypeScript

import { animated, CustomAnimation } from 'rani-motion';

// Define custom animation
const slideRotateAnim: CustomAnimation = {
  initial: { 
    opacity: 0, 
    transform: 'translateX(-100px) rotate(-90deg)' 
  },
  animate: { 
    opacity: 1, 
    transform: 'translateX(0px) rotate(0deg)' 
  }
};

// Use with animated.div
<animated.div 
  customAnimation={slideRotateAnim}
  duration={1200}
>
  <h2>Custom slide + rotate animation!</h2>
</animated.div>

// Or with component wrapper
<RaniOnView customAnimation={slideRotateAnim}>
  <div>Same custom animation</div>
</RaniOnView>

Hover Animations

import { RaniHover, CustomHoverAnimation } from 'rani-motion';

const glowHover: CustomHoverAnimation = {
  default: { 
    transform: 'scale(1)',
    filter: 'brightness(1) blur(0px)',
    boxShadow: '0 0 0px rgba(59, 130, 246, 0)'
  },
  hover: { 
    transform: 'scale(1.05)',
    filter: 'brightness(1.2) blur(1px)',
    boxShadow: '0 0 25px rgba(59, 130, 246, 0.6)'
  }
};

Stagger Animations

import { RaniStagger } from 'rani-motion';

const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

<RaniStagger 
  staggerDelay={150} 
  animation="scaleIn"
  duration={600}
>
  {items.map(item => (
    <div key={item} className="card">{item}</div>
  ))}
</RaniStagger>

Animation Provider & Context

import { RaniProvider, useRaniAnimation } from 'rani-motion';

function App() {
  return (
    <RaniProvider 
      globalDuration={800}
      globalEasing="easeOutBounce"
      reducedMotion={false}
    >
      <MyAnimatedApp />
    </RaniProvider>
  );
}

function MyAnimatedApp() {
  const { globalDuration, reducedMotion } = useRaniAnimation();
  
  return (
    <RaniOnView duration={globalDuration}>
      <div>Uses global settings</div>
    </RaniOnView>
  );
}

Accessibility & Reduced Motion

import { useReducedMotion } from 'rani-motion';

function AccessibleAnimation() {
  const prefersReducedMotion = useReducedMotion();
  
  return (
    <RaniOnView 
      animation={prefersReducedMotion ? 'fadeIn' : 'bounceInUp'}
      duration={prefersReducedMotion ? 200 : 800}
    >
      <div>Respects user motion preferences</div>
    </RaniOnView>
  );
}

Custom Hooks

import { useIntersectionObserver, useReducedMotion } from 'rani-motion';

function CustomAnimatedComponent() {
  // 접근성 고려
  const prefersReducedMotion = useReducedMotion();
  
  // 스크롤 감지
  const { elementRef, isIntersecting } = useIntersectionObserver({
    threshold: 0.3,
    triggerOnce: true
  });

  return (
    <div 
      ref={elementRef}
      style={{
        opacity: isIntersecting ? 1 : 0,
        transform: isIntersecting 
          ? 'translateY(0)' 
          : 'translateY(20px)',
        transition: prefersReducedMotion 
          ? 'opacity 0.2s ease' 
          : 'all 0.6s ease'
      }}
    >
      Custom intersection observer usage with accessibility
    </div>
  );
}

Props Reference

RaniOnViewProps

interface RaniOnViewProps {
  children: ReactNode;
  animation?: AnimationPreset;
  customAnimation?: CustomAnimation;
  duration?: number;          // default: 600
  delay?: number;             // default: 0
  easing?: EasingType;        // default: 'easeOutQuart'
  triggerOnce?: boolean;      // default: true
  threshold?: number;         // default: 0.1
  className?: string;
  style?: CSSProperties;
}

RaniHoverProps

interface RaniHoverProps {
  children: ReactNode;
  animation?: HoverPresetType;
  customAnimation?: CustomHoverAnimation;
  duration?: number;          // default: 300
  className?: string;
  style?: CSSProperties;
}

RaniClickProps

interface RaniClickProps {
  children: ReactNode;
  animation?: ClickPresetType;
  customAnimation?: CustomClickAnimation;
  onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
  className?: string;
  style?: CSSProperties;
}

RaniStaggerProps

interface RaniStaggerProps {
  children: ReactNode[];
  staggerDelay?: number;      // default: 100
  animation?: AnimationPreset;
  customAnimation?: CustomAnimation;
  duration?: number;          // default: 600
  className?: string;
  style?: CSSProperties;
}

Type Definitions

Animation Types

type AnimationPreset = 
  | 'fadeIn' | 'fadeInUp' | 'fadeInDown' | 'fadeInLeft' | 'fadeInRight'
  | 'slideInUp' | 'slideInDown' | 'slideInLeft' | 'slideInRight'
  | 'scaleIn' | 'scaleInUp' | 'zoomIn'
  | 'rotateIn' | 'rotateInLeft' | 'rotateInRight'
  | 'bounceIn' | 'bounceInUp'
  | 'flipInX' | 'flipInY'
  | 'lightSpeedIn' | 'rollIn';

type EasingType = 
  | 'linear' | 'easeIn' | 'easeOut' | 'easeInOut'
  | 'easeOutQuart' | 'easeInOutCubic' 
  | 'easeOutBounce' | 'easeOutElastic';

Custom Animation Interfaces

interface AnimationState {
  opacity?: number;
  transform?: string;
  filter?: string;
  boxShadow?: string;
  borderRadius?: string;
  [key: string]: string | number | undefined;
}

interface CustomAnimation {
  initial: AnimationState;
  animate: AnimationState;
}

interface CustomHoverAnimation {
  default: AnimationState;
  hover: AnimationState;
}

Features

  • 🚀 TypeScript First: Full type safety and IntelliSense support
  • 🎨 20+ Preset Animations: Ready-to-use animations for common use cases
  • 🛠️ Custom Animations: Define your own animations with full type safety
  • 📱 Responsive: Works perfectly on all screen sizes
  • Accessible: Respects prefers-reduced-motion settings
  • 🔧 Highly Configurable: Customize duration, delay, easing, and more
  • 📦 Tree Shakeable: Import only what you need
  • 🎯 Performance Optimized: Uses Intersection Observer for efficient scroll detection
  • 🎪 Zero Dependencies: No external animation libraries required

Browser Support

  • Chrome >= 60
  • Firefox >= 55
  • Safari >= 12
  • Edge >= 79

License

MIT © Rani Animation Library

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


Rani - Simple, powerful, and accessible React animations 🎪