Project: Kanban Task Board
In this project, we will build a Kanban Task Board. Users can create new tasks, update task descriptions, and move tasks between three pipeline columns: Todo, In Progress, and Done.
1. Component State Design
We will model our tasks as an array of objects. Each task has:
id: A unique timestamp identifier.title: The task title string.status: One of"todo","progress", or"done".
2. Implementing the Kanban Board
Create a new file named KanbanBoard.jsx and add the following implementation:
import { useState } from "react";
export function KanbanBoard() {
const [tasks, setTasks] = useState([
{ id: 1, title: "Review pull requests", status: "todo" },
{ id: 2, title: "Configure webpack split settings", status: "progress" },
{ id: 3, title: "Setup initial git repository", status: "done" }
]);
const [newTitle, setNewTitle] = useState("");
// Create a new task item
const addTask = (e) => {
e.preventDefault();
if (!newTitle.trim()) return;
const newTask = {
id: Date.now(),
title: newTitle.trim(),
status: "todo"
};
setTasks([...tasks, newTask]);
setNewTitle("");
};
// Move task to a different status column
const moveTask = (id, newStatus) => {
setTasks(prevTasks =>
prevTasks.map(task =>
task.id === id ? { ...task, status: newStatus } : task
)
);
};
// Delete task item
const deleteTask = (id) => {
setTasks(prevTasks => prevTasks.filter(task => task.id !== id));
};
const columns = [
{ label: "To Do", value: "todo", nextStatus: "progress" },
{ label: "In Progress", value: "progress", nextStatus: "done" },
{ label: "Done", value: "done", nextStatus: null }
];
return (
<div className="kanban-wrapper">
<form onSubmit={addTask} className="task-form">
<input
type="text"
value={newTitle}
onChange={(e) => setNewTitle(e.target.value)}
placeholder="Enter task name..."
/>
<button type="submit">Add Task</button>
</form>
<div className="kanban-grid">
{columns.map(col => (
<div key={col.value} className="kanban-column">
<h2>{col.label}</h2>
<div className="task-list">
{tasks
.filter(t => t.status === col.value)
.map(task => (
<div key={task.id} className="task-card">
<p>{task.title}</p>
<div className="task-actions">
{col.nextStatus && (
<button onClick={() => moveTask(task.id, col.nextStatus)}>
Move →
</button>
)}
<button onClick={() => deleteTask(task.id)} className="btn-delete">
Delete
</button>
</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}3. Styling the Kanban Grid
To present the columns side-by-side, use CSS Flexbox or Grid layouts:
.kanban-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-top: 30px;
}
.kanban-column {
background: #f4f5f7;
padding: 15px;
border-radius: 8px;
min-height: 400px;
}
.task-card {
background: white;
padding: 12px;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
margin-bottom: 10px;
}Published on Last updated: