Build a React Task Board
Computer Science
Build a React Task Board
Build a React Task Board
Turn your HTML and CSS foundation into an interactive React task board. You will first practice the React screen structure and click-driven state in small exercises, then use those skills to finish a runnable Task Board with tasks you can add and complete.
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
Practice the React Building Blocks
2 lessonsUse familiar HTML structure inside React components before introducing the Task Board project files.
Create the Task Board
1 lessonApply the practiced component and state patterns to the generated Vite project.
Finish a Runnable Board
1 lessonComplete the interaction and verify the project behaves as a usable web app.
Public lesson
Build a React Screen Shell
Build one React screen from small components
You already know how to shape a page with headings, sections, and links. In React, the page shape is still JSX—but you can move meaningful pieces into files and pass each piece the text it needs.
Build a shell for the full-stack app you’re working toward:
- a page header
- a small navigation area
- a workspace with two reusable panels
There is no API or state yet. The goal is to see how components combine into one screen.
Tasks
1. Start with the page shape
In src, create this folder:
components/
ScreenHeader.jsx
ContentPanel.jsx
components/
ScreenHeader.jsx
ContentPanel.jsx
Use capitalized filenames because these files will export React components.
Tasks
2. Make a header that receives its text as props
Create src/components/ScreenHeader.jsx.
export default function ScreenHeader({ title, description }) {
return (
<header className="screen-header">
<p className="eyebrow">MY APP</p>
<div>
<h1>{/* show title here */}</h1>
<p className="description">{/* show description here */}</p>
</div>
</header>
);
}
export default function ScreenHeader({ title, description }) {
return (
<header className="screen-header">
<p className="eyebrow">MY APP</p>
<div>
<h1>{/* show title here */}</h1>
<p className="description">{/* show description here */}</p>
</div>
</header>
);
}
Replace each comment with the matching prop name.
title and description came from the parentheses at the top. Curly braces let JSX display a JavaScript value.
Check: the file should have no red error underline, and both JSX elements should have closing tags.
Tasks
3. Make a reusable content panel
Create src/components/ContentPanel.jsx.
export default function ContentPanel({ heading, children }) {
return (
<section className="panel">
<h2>{/* show heading here */}</h2>
<div className="panel-content">
{/* render children here */}
</div>
</section>
);
}
export default function ContentPanel({ heading, children }) {
return (
<section className="panel">
<h2>{/* show heading here */}</h2>
<div className="panel-content">
{/* render children here */}
</div>
</section>
);
}
children means “whatever JSX is placed between this component’s opening and closing tags.” This lets the same panel frame hold different content.
Check: this component should use both props somewhere in its returned JSX.
Tasks
4. Assemble the screen in App.jsx
Open src/App.jsx. Keep the CSS import if your file already has one, then replace the starter page with this structure. Fill in the import paths, your app name, and the missing prop values yourself.
import ScreenHeader from /* path to your header component */;
import ContentPanel from /* path to your panel component */;
function App() {
const appName = "Choose a name for your app";
return (
<main className="app-shell">
<ScreenHeader
title={/* use appName */}
description="A short sentence describing what this screen helps with."
/>
<div className="screen-body">
<aside className="screen-nav">
<p className="nav-label">WORKSPACE</p>
<nav>
<a href="#overview">Overview</a>
<a href="#items">Your items</a>
<a href="#settings">Settings</a>
</nav>
</aside>
<section className="workspace">
<ContentPanel heading={/* a heading for the first panel */}>
<p>Write one sentence about what will eventually appear here.</p>
</ContentPanel>
<ContentPanel heading={/* a different heading */}>
<p>Add a second piece of placeholder content.</p>
</ContentPanel>
</section>
</div>
</main>
);
}
export default App;
import ScreenHeader from /* path to your header component */;
import ContentPanel from /* path to your panel component */;
function App() {
const appName = "Choose a name for your app";
return (
<main className="app-shell">
<ScreenHeader
title={/* use appName */}
description="A short sentence describing what this screen helps with."
/>
<div className="screen-body">
<aside className="screen-nav">
<p className="nav-label">WORKSPACE</p>
<nav>
<a href="#overview">Overview</a>
<a href="#items">Your items</a>
<a href="#settings">Settings</a>
</nav>
</aside>
<section className="workspace">
<ContentPanel heading={/* a heading for the first panel */}>
<p>Write one sentence about what will eventually appear here.</p>
</ContentPanel>
<ContentPanel heading={/* a different heading */}>
<p>Add a second piece of placeholder content.</p>
</ContentPanel>
</section>
</div>
</main>
);
}
export default App;
Use labels that fit your own app rather than treating “items” as a permanent feature. For example, a reading app might use “Saved books”; a task app might use “Today’s tasks.”
Tasks
Check in the browser:
- You see one page heading and its description.
- You see two panels with different headings.
- Change
appNameinApp.jsx. - The header text changes without editing
ScreenHeader.jsx.
That last check is the point of props: App owns the page’s content, while ScreenHeader owns how that content is displayed.
Tasks
5. Give the shell a simple layout
This CSS is only to make the component boundaries visible; paste it into src/App.css. If App.jsx does not already import that file, add:
import "./App.css";
import "./App.css";
* {
box-sizing: border-box;
}
body {
margin: 0;
background: #f5f6fa;
color: #1d2330;
font-family: Arial, sans-serif;
}
.app-shell {
min-height: 100vh;
}
.screen-header {
display: flex;
gap: 1.5rem;
align-items: start;
padding: 2rem max(1.5rem, 8vw);
background: #202a44;
color: white;
}
.eyebrow,
.nav-label {
margin: 0;
font-size: 0.75rem;
font-weight: bold;
letter-spacing: 0.08em;
}
.description {
margin-bottom: 0;
color: #dbe4ff;
}
.screen-body {
display: grid;
grid-template-columns: 190px 1fr;
gap: 2rem;
max-width: 1000px;
margin: 0 auto;
padding: 2rem;
}
.screen-nav nav {
display: grid;
gap: 0.75rem;
margin-top: 1rem;
}
.screen-nav a {
color: #34466f;
text-decoration: none;
}
.workspace {
display: grid;
gap: 1rem;
}
.panel {
padding: 1.5rem;
border: 1px solid #dce1eb;
border-radius: 12px;
background: white;
}
.panel h2 {
margin-top: 0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: #f5f6fa;
color: #1d2330;
font-family: Arial, sans-serif;
}
.app-shell {
min-height: 100vh;
}
.screen-header {
display: flex;
gap: 1.5rem;
align-items: start;
padding: 2rem max(1.5rem, 8vw);
background: #202a44;
color: white;
}
.eyebrow,
.nav-label {
margin: 0;
font-size: 0.75rem;
font-weight: bold;
letter-spacing: 0.08em;
}
.description {
margin-bottom: 0;
color: #dbe4ff;
}
.screen-body {
display: grid;
grid-template-columns: 190px 1fr;
gap: 2rem;
max-width: 1000px;
margin: 0 auto;
padding: 2rem;
}
.screen-nav nav {
display: grid;
gap: 0.75rem;
margin-top: 1rem;
}
.screen-nav a {
color: #34466f;
text-decoration: none;
}
.workspace {
display: grid;
gap: 1rem;
}
.panel {
padding: 1.5rem;
border: 1px solid #dce1eb;
border-radius: 12px;
background: white;
}
.panel h2 {
margin-top: 0;
}
Tasks
Final visual check: you should see a dark header, a left navigation column, and two white panels in the workspace.
If the page is blank, look first at the terminal or browser console:
- “Failed to resolve import”: check the filename, folder, and capitalization.
- “Unexpected token”: check JSX closing tags and braces.
- Header text missing: make sure
ScreenHeaderrenderstitleanddescriptionwith{}.
You now have one visible screen built from three responsibilities: App arranges the page, ScreenHeader displays header information, and ContentPanel provides a reusable frame for different content.
Course Outline
3 modules · 4 lessons
Practice the React Building Blocks
Create the Task Board
Finish a Runnable 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.