✨ What I Built

A clean and functional Todo App using React.js - mainly built to practice component structure, state management, and dark/light theming.

This version is desktop-only for now, but I plan to make it fully responsive later.

⚙️ Features

✅ Add new tasks
❌ Delete tasks
🕹️ Toggle task completion
🌗 Dark/Light mode toggle
🔍 Filter tasks by:

🔹All
🔷Active
✅Completed

🧹 Clear all completed tasks
🔄 Real-time updates using useState and props

🔧 Tech Stack

React.js (Functional Components + Hooks)
CSS Modules for scoped styling
No external UI libraries
Modular file structure

🎯 What I Practiced

Lifting and managing state between components
Controlled form elements
Dynamic filtering
Class toggling for theme switch
Code reusability (e.g., component)

🖼️ Screenshots

  • Main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  
    
  ,
)
  • App.jsx
import "./App.css";
import { useState } from "react";
import TodoHeader from "./components/TodoHeader";
import TodoForm from "./components/TodoForm";
import TodoList from "./components/TodoList";

function App() {
    const [isDarkMode, setIsDarkMode] = useState(false);
    const [todoItems, setTodoItems] = useState([]);

    const handleAddTodoItems = (item) => {
        setTodoItems((items) => [...items, item]);
    };

    const handleDeleteItems = (id) => {
        setTodoItems((items) => items.filter((item) => item.id !== id));
    };

    const handleToggleComplete = (id) => {
        setTodoItems((items) =>
            items.map((item) => (item.id === id ? { ...item, completed: !item.completed } : item))
        );
    };

    const handleClearCompleted = () => {
        setTodoItems((items) => items.filter((item) => !item.completed));
    };

    return (
        <>
            
                
                    
                    

                    {todoItems.length > 0 ? (
                        
                    ) : (
                        ""
                    )}
                
            
        >
    );
}

export default App;
  • TodoHeader.jsx
import "../styles/Header.css";
import Button from "./ui/Button";

function TodoHeader({ isDarkMode, onChangeTheme }) {
    const handleThemeToggler = () => {
        onChangeTheme((isDarkMode) => !isDarkMode);
    };

    return (
        
            Todo

            
                
            
        
    );
}

export default TodoHeader;
  • UI Button.jsx
function Button({ className, onClick, children, id }) {
    return (
        
            {children}
        
    );
}

export default Button;
  • TodoForm.jsx
import { useState } from "react";
import "../styles/TodoForm.css";
import Button from "./ui/Button";

function TodoForm({ onAddTodoItems }) {
    const [task, setTask] = useState("");

    const handleForm = (e) => {
        e.preventDefault();

        if (!task.trim()) return;

        const newTask = {
            id: Date.now(),
            task: task,
            completed: false,
        };

        onAddTodoItems(newTask);
        setTask("");
    };

    return (
        
            
                
                
                 setTask(e.target.value)}
                    value={task}
                />
            
        
    );
}

export default TodoForm;
  • TodoList.jsx
import TodoItem from "./TodoItem";
import "../styles/TodoList.css";
import TodoFooter from "./TodoFooter";
import { useState } from "react";

function TodoList({ todoItems, setTodoItems, onTaskComplete, onDeleteItem, onClearCompleted }) {
    const [activeTab, setActiveTab] = useState("all");

    let filterItems;

    if (activeTab === "all") filterItems = todoItems;
    else if (activeTab === "active")
        filterItems = todoItems.filter((item) => item.completed === false);
    else filterItems = todoItems.filter((item) => item.completed === true);

    return (
        <>
            
                {filterItems.map((item) => {
                    return (
                        
                    );
                })}
            
            
        >
    );
}
export default TodoList;
  • TodoItem.jsx
import Button from "./ui/Button";

function TodoItem({ item, onTaskComplete, onDeleteItem }) {
    return (
        
             onTaskComplete(item.id)}
            />
            
                
            

            {item.task}

             onDeleteItem(item.id)}>
                
            
        
    );
}

export default TodoItem;
  • TodoFooter.jsx
import Button from "./ui/Button";
import "../styles/TodoFooter.css";

const ctaBtnText = ["All", "Active", "Completed"];

function TodoFooter({ filter, onSetFilter, todoItems, onClearCompleted }) {
    const activeTodoItems = todoItems.filter((item) => !item.completed).length;

    return (
        
            {activeTodoItems} items left

            
                {ctaBtnText.map((btn) => (
                     onSetFilter(btn.toLocaleLowerCase())}
                    >
                        
                            {btn}
                        
                    
                ))}
            

            
                Clear Completed
            
        
    );
}

export default TodoFooter;

Let me know what you think or if you have any feedback! Cheers! 🚀