Skip to content

Adding some simple animations using Framer Motion [Optional]

In this part we will learn how to use Framer Motion library in React to add some simple animation. Framer Motion is really powerful library and it can do really advanced animations. Check it our here https://github.com/framer/motion.

First we need to add framer motion library to our project by executing the following command in the Terminal

npm install framer-motion

In this example, we will animate our ListItem to slide in from the top when it is added and to fade out when it is removed. We first need to update ListItem.tsx

import { Todo } from "../store/reducers/todo";
import { motion } from "framer-motion";

interface ListItemInterface {
    item: Todo;
    removeItemFromList: Function;
    toggleItemDone: Function;
}

function ListItem(props: ListItemInterface) {
    return (
        <motion.li
            animate={{ opacity: 1, y: '0' }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.5 }}
            className="flex items-center p-2 opacity-0 -translate-y-1/2"
        >
            <input
                onChange={() => props.toggleItemDone(props.item.id)}
                type="checkbox"
                className="h-4 w-4 mr-2 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"
                checked={props.item.is_done}
            />
            <p
                className={
                    "w-full" + (props.item.is_done ? " line-through" : "")
                }
            >
                {props.item.title}
            </p>
            <button
                onClick={() => props.removeItemFromList(props.item.id)}
                type="button"
                className="w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-2 py-0.5 bg-white text-base font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-1 focus:ring-offset-2 focus:ring-red-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
            >
                Remove
            </button>
        </motion.li>
    );
}

export default ListItem;

Also, since we are dealing with multiple items in the list when they are appearing and disappearing, we will need to wrap our list in <AnimatePresence>...</AnimatePresence>

To do this we will modify our List.tsx to:

import { AnimatePresence } from "framer-motion";
import { Todo } from "../store/reducers/todo";
import ListItem from "./ListItem";

interface ListInterface {
    list: Todo[];
    removeItemFromList: Function;
    toggleItemDone: Function;
}

function List(props: ListInterface) {
    return (
        <ul className="p-8 pt-0 divide-y">
            {props.list.length > 0 && (
                <AnimatePresence>
                    {props.list.map((todo_item: Todo) => (
                        <ListItem
                            key={todo_item.id}
                            item={todo_item}
                            removeItemFromList={props.removeItemFromList}
                            toggleItemDone={props.toggleItemDone}
                        />
                    ))}
                </AnimatePresence>
            )}
            {props.list.length < 1 && (
                <p>Your todo list is empty, please add some todo.</p>
            )}
        </ul>
    );
}

export default List;

And that is basically it, you learned basic animations using Framer Motion. Feel free to play with any type of animations on your own.


Congrats! You successfully created a Todo list client application in React.js.

But, there is more...