✨ 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! 🚀