Skip to content

webdevsk/react-todo-app

Repository files navigation


Logo

React TODO App

A TODO App based on React with dynamic Routing.

Explore the docs »

View Demo · Report Bug · Request Feature


Table of Contents

About The Project

Product snapshot


  • This is a simple TODO APP built with React.
  • It was built with handheld device accessibility in mind. Hence the bottom Input field.
  • It features dynamic routing and dynamic category using React Router.
  • Light, Dark and Auto theme. The auto theme follows system preferences.
  • Here's what users can expect from this APP:
    • Create Category for different types of tasks.
    • Create tasks for the respective category.
    • Mark completed task as done.
    • Bulk Mark all tasks as done.
    • Delete task.
    • Bulk delete completed tasks.
    • Mark task as important.
    • Important tasks get pinned to top.
    • Users can visit site_url/Groceries and add tasks directly to a category named Groceries.
    • Nice little rewarding animations when a task is completed. 😉

⭐ Head over to the Features section to dive deep into the problems I faced and how I solved them.

(back to top)

Built With

React
React-router
TailwindCSS
MUI

(back to top)

Getting Started

🌐 The site is already live at: https://celadon-cactus-42acbb.netlify.app/

OR

🖥️ You can test it on your local machine by following the steps below.

Prerequisites

  1. Install NODE.JS and Git

  2. Open your projects base folder and launch any terminal of your choice.

  3. Run this command:

    npm install npm@latest -g

Installation

  1. Clone the repo

    git clone https://github.com/webdevsk/react-todo-app.git
  2. Install NPM packages

    npm install
  3. Run Dev server

    npm run dev

(back to top)

Features

Menu desktop view

Desktop

Menu mobile view

Mobile

⭐ Handheld accessible layout

  • The input field is placed at the bottom making it is easily reachable on handheld devices.

  • Unlike most other Todo Apps, it featues top to bottom (old to new) layout.

  • As you add new tasks, the newer tasks will appear at the bottom.

  • The page will scroll down automatically to keep newer tasks in focus.

    ⚒️ Here's a snippet of code on how I solved the scroll issue:
    const {tasks, category} = useLoaderData()
    
    //Length of the task array before new task is added
    const prevLength = useRef(tasks.length)
    
    useEffect(() => {
      // Run only when new task is added
      if (prevLength.current < tasks.length){
        window.scrollTo({ left: 0, top: document.body.scrollHeight || document.documentElement.scrollHeight, behavior: "smooth" })
      }
      //Setting new task array length after new task is added
      prevLength.current = tasks.length
    }, [tasks])

⭐ Dynamic Drawer Menu

  • Larger screens

    • Side Drawer Menu can stay either Shown or Hidden based on user's preference.
    • The shown/hidden state is persisted between browsing sessions.
    • Clicking outside the menu will not close it.
  • Smaller screens (1400px or less)

    • Side Drawer Menu will always be Hidden unless user opens it.
    • Window size is consistently being monitored to check if the window goesbelow 1400px. If so the menu will hide automatically.
    • Clicking outside the menu will close it.
    ⚒️ Here's a snippet of code on how I solved it:
    //Initial state. Defaults to false on smaller screens
    const [open, setOpen] = useState(() => (
      window.outerWidth <= 1400
      ? false
      : 'drawerOpen' in localStorage
      ? true
      : false
    ))
    
    //Saves state in localStorage
    useEffect(()=> (
      open 
      ? localStorage.setItem('drawerOpen', '1') 
      : localStorage.removeItem('drawerOpen')
    ), [open])
    
    //Enables overlay on smaller screens. Which blurs outside content and listens to touch events
    const [overlay, setOverlay] = useState(() => window.outerWidth <= 1400)
    
    //Runs on window resize
    useEffect (()=>{
      let currentWindowWidth = window.outerWidth
    
      function handleWindowResize(){
        //Run only when the horizontal width changes to avoid firing on keyboard popup on touch devices
        if (window.outerWidth === currentWindowWidth) return
        currentWindowWidth = window.outerWidth
    
        if (window.outerWidth <= 1400){
          setOpen(false)
          setOverlay(true)
        } else {
          setOverlay(false)
        }
      }
      
      window.addEventListener('resize', handleWindowResize)
      return () => {
        window.removeEventListener('resize', handleWindowResize)
      }
    }, [])

⭐ Create your own Categories


  • Click on the "Add new category" button and type your desired name for it.
  • Press Enter or click on the ✅ (tick) button.
  • You will be redirected to a new page where you can add tasks in this category.
  • Visit or Bookmark https://celadon-cactus-42acbb.netlify.app/School
    • If you already had tasks in School category, the tasks will be listed.
    • If you never had a School category, it will generate a new Category where you can add new tasks.
    • You can write any strings in place of "School".
    • If you want to add spaces or symbols in category name, rather create it from the Side Drawer Menu instead.
  • To save up space in Database/storage, A category won't be stored unless you have atleast 1 task in it.

⭐ Bulk Operations


  • Completed all tasks for today? Well, congratulations!!! The "Mark all as completed" button will be handy then.
  • No need to clutter the list with already complted tasks. The "Delete All Completed" button will make them go away.

And many more handmade features, animations here and there...

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Contact

Follow on GitHub Follow on Linkedin

Project Link: https://github.com/webdevsk/react-todo-app

(back to top)