Add a "Sepia" filter to vanilla PixelCraft:
| # | Change | File |
|---|---|---|
| 1 | Add button HTML | index.html |
| 2 | Add CSS | styles.css |
| 3 | Add event listener | ui.js |
| 4 | Add to filter state | state.js |
| 5 | Update slider | ui.js |
| 6 | Update keyboard shortcut | ui.js |
| 7 | Update export metadata | canvas.js |
npm create vite@latest pixelcraft-react -- --template react
cd pixelcraft-react && npm install
npm run dev
Open http://localhost:5173. You now have a running React app with hot reload — edit code, see changes instantly without refreshing.
function ToolButton({ name, icon, onClick, active }) {
return (
<button
className={`tool-btn ${active ? 'active' : ''}`}
onClick={onClick}
title={name}
>
{icon} {name}
</button>
);
}
function Toolbar({ tools, activeTool, onToolSelect }) {
return (
<nav className="toolbar">
{tools.map(tool => (
<ToolButton
key={tool.id}
name={tool.name}
icon={tool.icon}
active={activeTool === tool.id}
onClick={() => onToolSelect(tool.id)}
/>
))}
</nav>
);
}
| Aspect | Vanilla Toolbar | React Toolbar |
|---|---|---|
| Lines of code | ~50 lines DOM manipulation | ~15 lines JSX |
| Add a tool | HTML + CSS + JS + state | 1 object in array |
| Active state | Manual classList toggle | Derived from props |
| Paradigm | Imperative | Declarative |
The paradigm shift: describe WHAT the UI should look like → React handles the DOM updates.
git switch -c refactor/PIXELCRAFT-028-react-migration
git add .
git commit -m "Set up React + Vite, migrate toolbar component (PIXELCRAFT-028)"
git push origin refactor/PIXELCRAFT-028-react-migration
# PR → Review → Merge → Close ticket ✅
Declarative programming.
React is declarative: "here's what the toolbar should look like given this data." The previous imperative approach was: "find the button, change its class, update the text, add a listener."