Why Build a Component Library?
- Reuse animations without rewriting code
- Keep your UI consistent across projects
- Make it easy for teammates (or your future self)
- Learn how to structure scalable React components
Step 1: Setup
Install React + Framer Motion:
npm install framer-motion
Create a folder structure like this:
animated-components/
│
├── src/
│ ├── components/
│ │ ├── AnimatedButton.jsx
│ │ ├── AnimatedCard.jsx
│ │ ├── AnimatedModal.jsx
│ │
│ └── index.js
│
├── example/ # Demo playground
│ ├── App.jsx
│ └── index.js
│
├── package.json
├── README.md
└── vite.config.js (or Next.js if you prefer)
Step 2: Create an Animated Button
// components/AnimatedButton.jsx
import { motion } from "framer-motion";
export default function AnimatedButton({ children, onClick }) {
return (
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className="px-4 py-2 bg-indigo-500 text-white rounded-lg shadow"
onClick={onClick}
>
{children}
</motion.button>
);
}
Step 3: Create an Animated Card
// components/AnimatedCard.jsx
import { motion } from "framer-motion";
export default function AnimatedCard({ children }) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: "easeOut" }}
className="p-6 bg-white rounded-xl shadow-md"
>
{children}
</motion.div>
);
}
Step 4: Create an Animated Modal
// components/AnimatedModal.jsx
import { motion, AnimatePresence } from "framer-motion";
export default function AnimatedModal({ isOpen, onClose, children }) {
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50"
onClick={onClose}
>
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.8, opacity: 0 }}
transition={{ duration: 0.3 }}
className="bg-white p-6 rounded-xl shadow-lg"
onClick={(e) => e.stopPropagation()}
>
{children}
</motion.div>
</motion.div>
)}
</AnimatePresence>
);
}
Step 5: Export from index.js
// index.js
export { default as AnimatedButton } from "./components/AnimatedButton";
export { default as AnimatedCard } from "./components/AnimatedCard";
export { default as AnimatedModal } from "./components/AnimatedModal";
Now you have a mini animated component library ready to import anywhere:
import { AnimatedButton, AnimatedCard, AnimatedModal } from "./components";
Step 6: Demo App (example/)
This is where users can see your components in action.
// example/App.jsx
import { useState } from "react";
import { AnimatedButton, AnimatedCard, AnimatedModal } from "../src";
export default function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="p-8 space-y-6">
<AnimatedCard>
<h2 className="text-xl font-bold">Hello from Animated Card 🎉</h2>
</AnimatedCard>
<AnimatedButton onClick={() => setIsOpen(true)}>
Open Modal
</AnimatedButton>
<AnimatedModal isOpen={isOpen} onClose={() => setIsOpen(false)}>
<h2 className="text-lg font-bold">I am an Animated Modal 🚀</h2>
</AnimatedModal>
</div>
);
}
Step 7: Docs + GitHub
- Create a README.md with installation + usage instructions.
- Push to GitHub.
- Add a demo site using Vite or Next.js + GitHub Pages / Vercel.
Step 8: Publish to npm
You can even publish this as an npm package so others can install it:
npm login
npm publish --access public
Then developers can do:
npm install animated-components-lib
And use it like:
import { AnimatedButton } from "animated-components-lib";
Top comments (0)