easy-form-animations
v0.1.0
Published
A gentle animation library for React forms & buttons - smooth, accessible animations without complexity
Maintainers
Readme
Easy Form Animations
A gentle animation library for React forms & buttons - smooth, accessible animations without complexity.
✨ 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-motionsystem 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 stylesize:'sm' | 'md' | 'lg'- Button sizeloading:boolean- Loading state with spinneranimation:AnimationVariant- Hover animation typeconfig: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 textanimation:AnimationVariant- Entry animationerror:string- Error message (shows red styling)helperText:string- Additional guidance textsize:'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 textoptions:Array<{ value: string, label: string }>- Select optionsanimation:AnimationVariant- Entry animationplaceholder: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 textrows:number- Number of visible text linesresize:'none' | 'both' | 'horizontal' | 'vertical'- Resize behavioranimation: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 textcolor:'primary' | 'secondary' | 'success' | 'warning' | 'error'- Color themesize:'sm' | 'md' | 'lg'- Checkbox sizehelperText: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 valuelabel:string- Radio button labelanimation:AnimationVariant- Selection animationcolor: Same as AnimatedCheckboxdescription: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 timingstaggerChildren: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 devBuilding
npm run buildThis builds the library using tsup, generating:
dist/index.js- CommonJS builddist/index.mjs- ESM builddist/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 unionsFormAnimationConfig- Form container configurationButtonAnimationConfig- Button-specific animation settingsEaseKitProps- 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-motionsystem 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
