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

easy-form-animations

v0.1.0

Published

A gentle animation library for React forms & buttons - smooth, accessible animations without complexity

Readme

Easy Form Animations

A gentle animation library for React forms & buttons - smooth, accessible animations without complexity.

License: MIT

✨ Features

  • 🎭 Gentle Animations - Smooth, accessible animations that enhance UX without being distracting
  • Lightweight - Built on Framer Motion with minimal bundle impact (~15KB gzipped)
  • 🎪 TypeScript Native - Full TypeScript support with comprehensive type definitions
  • Accessible - Respects prefers-reduced-motion system preferences
  • 🔧 Plug & Play - Drop-in components that work out of the box with sensible defaults
  • 🎨 Highly Customizable - Fine-tune animations, colors, and behaviors to match your design
  • 📱 Responsive - Works seamlessly across all device sizes

🚀 Installation

npm install easy-form-animations framer-motion clsx
# or
yarn add easy-form-animations framer-motion clsx
# or
pnpm add easy-form-animations framer-motion clsx

🏁 Quick Start

import { AnimatedForm, AnimatedInput, AnimatedButton } from 'easy-form-animations';
import { useState } from 'react';

export default function MyForm() {
  const [email, setEmail] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);

  return (
    <AnimatedForm config={{ staggerChildren: 0.1 }}>
      <AnimatedInput 
        label="Email"
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        animation="slideUp"
        required 
      />
      
      <AnimatedButton 
        variant="primary" 
        type="submit"
        loading={isSubmitting}
        config={{ rippleEffect: true }}
      >
        Submit
      </AnimatedButton>
    </AnimatedForm>
  );
}

📚 API Reference

AnimatedButton

Interactive button with hover effects, loading states, and smooth animations.

<AnimatedButton
  variant="primary"        // Button style (primary, secondary, outline, ghost)
  size="md"               // Button size (sm, md, lg)
  loading={false}         // Shows loading spinner and disables button
  animation="gentle"      // Hover animation (gentle, bounce, scale, glow)
  config={{               // Animation configuration
    rippleEffect: true,
    hoverScale: 1.05,
    glowColor: '#3b82f6'
  }}
>
  Submit
</AnimatedButton>

Props:

  • variant: 'primary' | 'secondary' | 'outline' | 'ghost' - Button style
  • size: 'sm' | 'md' | 'lg' - Button size
  • loading: boolean - Loading state with spinner
  • animation: AnimationVariant - Hover animation type
  • config: ButtonAnimationConfig - Custom animation settings
  • Plus all standard button HTML attributes

AnimatedInput

Form input with floating label and smooth focus transitions.

<AnimatedInput
  label="Email Address"   // Floating label text
  type="email"           // Input type (text, email, password, etc.)
  animation="slideUp"    // Entry animation (fadeIn, slideUp, slideDown, scaleIn)
  error="Email required" // Error message (shows red styling)
  helperText="We'll never share your email"  // Additional guidance text
  size="md"              // Input size (sm, md, lg)
/>

Props:

  • label: string - Floating label text
  • animation: AnimationVariant - Entry animation
  • error: string - Error message (shows red styling)
  • helperText: string - Additional guidance text
  • size: 'sm' | 'md' | 'lg' - Input size
  • All standard HTML input attributes

AnimatedSelect

Dropdown select with animated labels and smooth transitions.

<AnimatedSelect
  label="Country"        // Floating label text
  options={[             // Select options array
    { value: 'us', label: 'United States' },
    { value: 'ca', label: 'Canada' }
  ]}
  animation="slideUp"    // Entry animation
  placeholder="Choose your country"
/>

Props:

  • label: string - Floating label text
  • options: Array<{ value: string, label: string }> - Select options
  • animation: AnimationVariant - Entry animation
  • placeholder: string - Placeholder text
  • All standard HTML select attributes

AnimatedTextarea

Multi-line text input with floating labels and resizable options.

<AnimatedTextarea
  label="Message"        // Floating label text
  rows={4}              // Number of visible text lines
  resize="vertical"     // Resize behavior (none, both, horizontal, vertical)
  animation="fadeIn"    // Entry animation
  placeholder="Tell us more..."
/>

Props:

  • label: string - Floating label text
  • rows: number - Number of visible text lines
  • resize: 'none' | 'both' | 'horizontal' | 'vertical' - Resize behavior
  • animation: AnimationVariant - Entry animation
  • All standard HTML textarea attributes

AnimatedCheckbox

Checkbox with smooth check animation and custom styling.

<AnimatedCheckbox
  label="Subscribe to newsletter"  // Checkbox label text
  checked={isChecked}              // Controlled checkbox state
  onChange={(e) => setIsChecked(e.target.checked)}
  animation="bounce"               // Check animation (gentle, bounce, scale, slide)
  color="primary"                  // Color theme (primary, secondary, success, warning, error)
  size="md"                       // Checkbox size (sm, md, lg)
  helperText="Get updates about new features"
/>

Props:

  • label: string - Checkbox label text
  • color: 'primary' | 'secondary' | 'success' | 'warning' | 'error' - Color theme
  • size: 'sm' | 'md' | 'lg' - Checkbox size
  • helperText: string - Additional text below checkbox
  • All standard HTML input[type="checkbox"] attributes

AnimatedRadio

Radio buttons with selection animations and group management.

<AnimatedRadioGroup value={selected} onChange={setSelected} name="options">
  <AnimatedRadio value="option1" label="Option 1" />
  <AnimatedRadio value="option2" label="Option 2" />
</AnimatedRadioGroup>

Props:

  • value: string - Radio button value
  • label: string - Radio button label
  • animation: AnimationVariant - Selection animation
  • color: Same as AnimatedCheckbox
  • description: string - Optional description text

AnimatedForm

Container that orchestrates child component animations with staggered timing.

<AnimatedForm 
  onSubmit={handleSubmit}
  config={{ staggerChildren: 0.1 }}
>
  {/* Form components */}
</AnimatedForm>

Props:

  • config: FormAnimationConfig - Configuration for stagger timing
    • staggerChildren: number - Delay between child animations (default: 0.05)
    • delayChildren: number - Initial delay before starting animations
  • All standard HTML form attributes

🎯 Complete Example

import React, { useState } from 'react';
import {
  AnimatedForm, 
  AnimatedInput, 
  AnimatedSelect, 
  AnimatedTextarea, 
  AnimatedCheckbox,
  AnimatedButton 
} from 'easy-form-animations';

export default function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    subject: '',
    message: '',
    newsletter: false
  });
  
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  const subjects = [
    { value: 'general', label: 'General Inquiry' },
    { value: 'support', label: 'Support Request' },
    { value: 'business', label: 'Business Partnership' }
  ];

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setIsSubmitting(true);
    
    try {
      // Your API call here
      await submitForm(formData);
      alert('Form submitted successfully!');
    } catch (error) {
      alert('Error submitting form');
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleChange = (field: string) => (
    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>
  ) => {
    const { value, type } = e.target;
    const checked = (e.target as HTMLInputElement).checked;
    
    setFormData(prev => ({
      ...prev,
      [field]: type === 'checkbox' ? checked : value
    }));
  };

  return (
    <div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg">
      <h2 className="text-2xl font-bold mb-6 text-center">Contact Us</h2>
      
      <AnimatedForm 
        onSubmit={handleSubmit}
        config={{ staggerChildren: 0.1, delayChildren: 0.2 }}
        className="space-y-4"
      >
        <AnimatedInput
          label="Full Name"
          value={formData.name}
          onChange={handleChange('name')}
          animation="slideUp"
          required
        />

        <AnimatedInput
          label="Email Address"
          type="email"
          value={formData.email}
          onChange={handleChange('email')}
          animation="slideUp"
          required
        />

        <AnimatedSelect
          label="Subject"
          value={formData.subject}
          onChange={handleChange('subject')}
          options={subjects}
          animation="slideUp"
          placeholder="Choose a subject"
        />

        <AnimatedTextarea
          label="Message"
          value={formData.message}
          onChange={handleChange('message')}
          animation="slideUp"
          rows={4}
          placeholder="Tell us how we can help..."
          required
        />

        <AnimatedCheckbox
          label="Subscribe to newsletter"
          checked={formData.newsletter}
          onChange={handleChange('newsletter')}
          helperText="Get updates about new features"
          animation="bounce"
          color="primary"
        />

        <AnimatedButton
          type="submit"
          variant="primary"
          size="lg"
          loading={isSubmitting}
          config={{ rippleEffect: true }}
          className="w-full"
        >
          {isSubmitting ? 'Sending...' : 'Send Message'}
        </AnimatedButton>
      </AnimatedForm>
    </div>
  );
}

🏗️ Project Structure

easy-form-animations/
├── src/
│   └── lib/
│       └── easy-form-animations/
│           ├── index.ts                 # Main exports
│           ├── types.ts                 # TypeScript definitions
│           ├── animations/
│           │   └── variants.ts          # Animation variants
│           ├── components/
│           │   ├── AnimatedButton.tsx   # Button component
│           │   ├── AnimatedCheckbox.tsx # Checkbox component
│           │   ├── AnimatedForm.tsx     # Form container
│           │   ├── AnimatedInput.tsx    # Input component
│           │   ├── AnimatedRadio.tsx    # Radio component
│           │   ├── AnimatedSelect.tsx   # Select component
│           │   └── AnimatedTextarea.tsx # Textarea component
│           └── hooks/
│               ├── useButtonAnimation.ts # Button animation logic
│               └── useFormAnimation.ts   # Form animation logic
├── dist/                                # Built files
├── package.json
├── tsconfig.json
├── tsup.config.ts                       # Build configuration
└── README.md

🛠️ Development

Prerequisites

  • Node.js 18+
  • npm, yarn, or pnpm

Local Development

# Clone the repository
git clone https://github.com/chetansoni1986/easy-form-animations.git
cd easy-form-animations

# Install dependencies
npm install

# Build the library
npm run build

# Watch for changes during development
npm run dev

Building

npm run build

This builds the library using tsup, generating:

  • dist/index.js - CommonJS build
  • dist/index.mjs - ESM build
  • dist/index.d.ts - TypeScript definitions

🔧 TypeScript Support

This library is written in TypeScript and provides comprehensive type definitions:

import type {
  AnimatedButtonProps, 
  AnimatedInputProps,
  FormAnimationConfig,
  ButtonAnimationConfig,
  AnimationVariant
} from 'easy-form-animations';

const buttonConfig: ButtonAnimationConfig = {
  rippleEffect: true,
  hoverScale: 1.05
};

const animation: AnimationVariant = 'slideUp';

Available Types

  • AnimationVariant - Animation type unions
  • FormAnimationConfig - Form container configuration
  • ButtonAnimationConfig - Button-specific animation settings
  • EaseKitProps - Base props for all animated components
  • Component-specific prop types for each component

🎨 Design Philosophy

Easy Form Animations is built around core principles:

Accessibility First

  • Honors prefers-reduced-motion system preferences
  • Keyboard navigation support
  • Screen reader compatibility
  • WCAG 2.1 AA compliance

Performance Focused

  • Minimal bundle size (~15KB gzipped)
  • Efficient animations using Framer Motion
  • Tree-shakeable exports
  • Zero runtime dependencies beyond peer deps

Developer Experience

  • TypeScript-first development
  • Intuitive component APIs
  • Comprehensive documentation
  • Sensible defaults with full customization

Animation Principles

  • Gentle by default - Subtle animations that enhance rather than distract
  • Purposeful motion - Every animation serves a functional purpose
  • Consistent timing - Harmonious animation curves and durations
  • Respectful of preferences - Adapts to user accessibility needs

📄 License

MIT License - see LICENSE file for details.

🐛 Issues & Contributing

We welcome contributions! Please see our contributing guidelines.

Reporting Issues

Found a bug? Please report it on our GitHub Issues page with:

  • Clear description of the issue
  • Steps to reproduce
  • Expected vs actual behavior
  • Browser/environment details

Made with ❤️ by Chetan Soni