Command Palette

Search for a command to run...

Animations

Create beautiful, performant animations for modern web applications using React, Motion, and CSS.

Animations enhance user experience by providing visual feedback, guiding attention, and creating delightful interactions. This guide provides practical examples and best practices for implementing animations in Next.js applications.

Smooth number transitions with NumberFlow for counters, statistics, and progress indicators. Perfect for dashboards and data visualizations.

Animated Counter
Smooth number transitions for counters and statistics
0

import NumberFlow from '@number-flow/react';import { useState } from 'react';function AnimatedCounter() {  const [count, setCount] = useState(0);  return (    <div className="flex items-center gap-4">      <button onClick={() => setCount(c => c - 1)}>-</button>      <NumberFlow        value={count}        locales="en-US"        format={{ useGrouping: false }}        className="text-2xl font-bold"        willChange      />      <button onClick={() => setCount(c => c + 1)}>+</button>    </div>  );}
Progress Indicator
Animated progress bars with smooth number transitions
Progress
0%

Delightful icon animations using Motion (Framer Motion) for scale, rotation, and state changes. Add personality to your interface interactions.

Interactive Icons
Icon animations with scale, rotation, and state changes

import { motion, AnimatePresence } from 'motion/react';import { Heart, Copy, Check } from 'lucide-react';import { useState } from 'react';function AnimatedIcon() {  const [isLiked, setIsLiked] = useState(false);  const [isCopied, setIsCopied] = useState(false);  return (    <div className="flex items-center gap-4">      <button onClick={() => setIsLiked(!isLiked)}>        <motion.div          animate={{            scale: isLiked ? [1, 1.2, 1] : 1,            rotate: isLiked ? [0, -10, 10, 0] : 0,          }}          transition={{ duration: 0.3 }}        >          <Heart className={isLiked ? "fill-pink-500" : ""} />        </motion.div>      </button>      <button onClick={() => setIsCopied(true)}>        <AnimatePresence mode="wait">          {isCopied ? (            <motion.div              key="check"              initial={{ scale: 0, opacity: 0 }}              animate={{ scale: 1, opacity: 1 }}              exit={{ scale: 0, opacity: 0 }}            >              <Check />            </motion.div>          ) : (            <motion.div              key="copy"              initial={{ scale: 0, opacity: 0 }}              animate={{ scale: 1, opacity: 1 }}              exit={{ scale: 0, opacity: 0 }}            >              <Copy />            </motion.div>          )}        </AnimatePresence>      </button>    </div>  );}

Animate layout changes automatically when items are added, removed, or reordered. Perfect for dynamic lists and grids.

import { motion, AnimatePresence } from 'motion/react';function LayoutAnimation() {  const [items, setItems] = useState([1, 2, 3]);  const addItem = () => {    setItems(prev => [...prev, prev.length + 1]);  };  const removeItem = (id) => {    setItems(prev => prev.filter(item => item !== id));  };  return (    <div>      <button onClick={addItem}>Add Item</button>      <motion.div layout className="space-y-2">        <AnimatePresence>          {items.map(item => (            <motion.div              key={item}              layout              initial={{ opacity: 0, scale: 0.8 }}              animate={{ opacity: 1, scale: 1 }}              exit={{ opacity: 0, scale: 0.8 }}              className="p-4 bg-muted rounded"            >              Item {item}              <button onClick={() => removeItem(item)}>Remove</button>            </motion.div>          ))}        </AnimatePresence>      </motion.div>    </div>  );}

Lightweight CSS animations for hover effects, loading states, and transitions. No JavaScript required for simple animations.

/* Smooth transitions */.transition-smooth {  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);}/* Hover effects */.hover-lift {  transition: transform 0.2s ease;}.hover-lift:hover {  transform: translateY(-2px);}/* Loading animations */@keyframes pulse {  0%, 100% { opacity: 1; }  50% { opacity: 0.5; }}.animate-pulse {  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;}/* Stagger animations */.stagger-item {  animation: fadeInUp 0.6s ease forwards;  opacity: 0;  transform: translateY(20px);}.stagger-item:nth-child(1) { animation-delay: 0.1s; }.stagger-item:nth-child(2) { animation-delay: 0.2s; }.stagger-item:nth-child(3) { animation-delay: 0.3s; }@keyframes fadeInUp {  to {    opacity: 1;    transform: translateY(0);  }}

Animation Principles

Timing

Use appropriate durations (200-300ms for micro-interactions) and easing functions for natural motion.

Purpose

Every animation should serve a clear functional purpose: feedback, guidance, or delight.

Performance

Optimize for 60fps using transform and opacity. Avoid animating layout properties like width or height.

Accessibility

Respect user preferences for reduced motion using the prefers-reduced-motion media query.

Best Practices

Performance Guidelines

Use transform and opacity for smooth 60fps animations

Avoid animating layout properties (width, height, top)

Use will-change sparingly and remove after animation

Test performance on lower-end devices

User Experience Guidelines

Keep animations under 300ms for micro-interactions

Use easing functions (ease-out, ease-in-out) for natural motion

Respect prefers-reduced-motion for accessibility

Provide meaningful feedback for user actions