Build a Polished React Task Board
Computer Science
Build a Polished React Task Board
Build a Polished React Task Board
Turn your existing React and CSS foundations into a task board you can actually use: add tasks, complete them, filter what matters, and keep the board between visits. You will finish with a polished Vite app that runs locally, builds successfully, and has a tested task-filtering behavior.
What you learn by building this
Build it yourself, get guided when you are stuck, and leave with proof you can actually show.
Learning Journey
Shape the Board and Make It Interactive
2 lessonsCreate the visual task-board experience first, then give its core actions real React state.
Finish, Verify, and Keep the Board
2 lessonsUse the working application to add useful task views, verify its behavior, and preserve the learner's work across browser refreshes.
Public lesson
Create the Task Board UI Shell
Build the Task Board UI Shell
Today you’ll turn the Vite React workspace into a polished static task board. No state or button behavior yet—the goal is to make the screen clear enough that adding behavior later feels natural.
By the end, your page should include:
- Task Board heading and short description
- A summary showing task counts
- An add-task form
- Filter controls
- Several styled task cards with different statuses
Tasks
1. Start with the visible structure
Run the project and open the page in your browser:
npm run dev
npm run dev
In src/App.jsx (or src/App.tsx), remove the starter Vite content and sketch the main regions first.
Use semantic elements where they fit:
function App() {
return (
<main className="board-page">
<header className="board-header">
{/* heading and intro */}
</header>
<section className="summary-section">
{/* summary cards */}
</section>
<section className="task-form-section">
{/* add-task form */}
</section>
<section className="tasks-section">
{/* filters and task cards */}
</section>
</main>
);
}
function App() {
return (
<main className="board-page">
<header className="board-header">
{/* heading and intro */}
</header>
<section className="summary-section">
{/* summary cards */}
</section>
<section className="task-form-section">
{/* add-task form */}
</section>
<section className="tasks-section">
{/* filters and task cards */}
</section>
</main>
);
}
Add your own heading text, such as Task Board, and one short sentence beneath it.
Check: the old Vite logo/counter is gone, and your page shows a heading in the browser.
2. Create a reusable summary card
Your summary should quickly answer: How much work is there, and what is its state?
Create a SummaryCard component, either in App.jsx first or as a file in src/components/.
It needs two props:
- a label, such as
"To do" - a number, such as
3
Tasks
Start with this shape, then choose your own class names and markup:
function SummaryCard({ label, count }) {
return (
<article className="...">
<p className="...">{label}</p>
<strong className="...">{count}</strong>
</article>
);
}
function SummaryCard({ label, count }) {
return (
<article className="...">
<p className="...">{label}</p>
<strong className="...">{count}</strong>
</article>
);
}
Render at least three cards:
- To do
- In progress
- Done
Use numbers that match the task cards you plan to show later.
Check: you can change one count value in the component call and see only that card’s number change.
3. Add the task form
Below the summary, build a form that looks ready to add a task, even though it will not submit anything yet.
Include:
- a text input for the task title
- a select control for priority
- an Add task button
Use labels, not only placeholders. A placeholder disappears when someone types; a label keeps explaining the field.
Tasks
Your structure might begin like this:
<form className="...">
<div className="...">
<label htmlFor="task-title">...</label>
<input id="task-title" type="text" placeholder="..." />
</div>
{/* priority field */}
<button type="button">Add task</button>
</form>
<form className="...">
<div className="...">
<label htmlFor="task-title">...</label>
<input id="task-title" type="text" placeholder="..." />
</div>
{/* priority field */}
<button type="button">Add task</button>
</form>
Use type="button" for now so clicking it does not refresh the page.
Check: clicking into the title field lets you type, choosing a priority works, and clicking Add task leaves the screen in place.
4. Make a TaskCard component
Task cards repeat the same kind of information, so they are a good place to practice components and props.
Each card should display:
- task title
- a short description
- priority
- status
- optional due text, such as “Due Friday”
Create a TaskCard component that receives those values as props. Do not hard-code one specific task inside the component; the component should describe the shape of any task card.
Tasks
A useful starting point:
function TaskCard({ title, description, priority, status, dueText }) {
return (
<article className="task-card">
<div className="task-card__top">
{/* title and status badge */}
</div>
<p className="task-card__description">{description}</p>
<footer className="task-card__meta">
{/* priority and due text */}
</footer>
</article>
);
}
function TaskCard({ title, description, priority, status, dueText }) {
return (
<article className="task-card">
<div className="task-card__top">
{/* title and status badge */}
</div>
<p className="task-card__description">{description}</p>
<footer className="task-card__meta">
{/* priority and due text */}
</footer>
</article>
);
}
Render at least four cards with believable tasks for a small project. Include a mix of:
- one high-priority task
- one task in progress
- one completed task
Check: changing the status prop on one card changes the visible status text for that card only.
Tasks
5. Add filters above the cards
Place filter controls between the “Tasks” heading and the card list.
Include buttons or controls for:
- All
- To do
- In progress
- Done
One filter should look selected, such as All. They do not need to filter the cards yet.
Give the selected control an extra class—for example, filter-button--active—so CSS can distinguish it.
Check: the active filter has a clearly different background, border, or text color from the other filters.
Tasks
6. Style the board in your CSS file
Open src/index.css or the stylesheet already imported by your app. First, add a small reset and page foundation:
* {
box-sizing: border-box;
}
body {
margin: 0;
/* choose your font, background, and text color */
}
* {
box-sizing: border-box;
}
body {
margin: 0;
/* choose your font, background, and text color */
}
Then style these areas in this order:
.board-page— centered layout with a sensible maximum width- header — space between heading, description, and summary
- summary cards — a responsive row/grid
- form — grouped fields and a prominent button
- filters — compact horizontal controls
- task cards — readable title, metadata, and status badges
Aim for a calm dashboard feel:
- light page background
- white cards
- subtle borders or shadows
- rounded corners
- one accent color for the main action
- different badge colors for statuses
Tasks
For the task list, try CSS Grid:
.task-list {
display: grid;
grid-template-columns: repeat( /* choose a value */, minmax(0, 1fr) );
gap: /* choose spacing */;
}
.task-list {
display: grid;
grid-template-columns: repeat( /* choose a value */, minmax(0, 1fr) );
gap: /* choose spacing */;
}
Use a media query so narrow screens show one task card per row:
@media (max-width: 640px) {
.task-list {
/* make the layout fit a phone */
}
.task-form-section form {
/* stack controls if needed */
}
}
@media (max-width: 640px) {
.task-list {
/* make the layout fit a phone */
}
.task-form-section form {
/* stack controls if needed */
}
}
Check: shrink the browser window. The page should not create a horizontal scrollbar, and cards should remain easy to read.
Tasks
7. Final visual review
Before stopping, compare your screen to this checklist:
- “Task Board” is the clearest thing on the page.
- Summary counts are visible near the top.
- The form visually invites someone to add a task.
- Filters look clickable, with one active choice.
- Each task card makes title, status, and priority easy to scan.
- The layout works at both desktop and narrow mobile widths.
- Nothing needs to work yet except normal browser inputs; this is a static UI shell.
Keep your TaskCard and SummaryCard components. In the next step, the form and filters can gain behavior without needing to rebuild the layout.
Course Outline
2 modules · 4 lessons
Shape the Board and Make It Interactive
Finish, Verify, and Keep the Board
Learn by building your own version.
Remix this public project to open the workspace, follow the guided build, and let the AI mentor teach you through the work instead of doing it for you.