A canvas editor built with React, Redux, and Konva.js for creating image layouts.
npm install
npm startOpen http://localhost:3000 in your browser.
npm run build- Header: Title and undo/redo buttons
- Sidebar: Library of available items
- Canvas: Editing area on the right
From Library:
- Click "Add" button on any library card
- Item appears on canvas at (50, 50)
- "Add" button becomes "Added" and disabled
Custom Images:
- Click "+ Add Custom Image" card
- Select image file
- Automatically added to library and canvas
Select: Click any item on canvas
- Shows colored border and resize handles
- Delete button (×) appears top-right
- Sidebar item highlights
Move: Drag selected item
- Only selected items can be dragged
- Stays within canvas boundaries
- Works when rotated
Resize: Drag corner/edge handles
- Minimum size: 20x20 pixels
- Respects canvas boundaries
Rotate: Drag rotation handle (circle above item)
- Rotates around center
- Auto-adjusts to stay in bounds
Delete: Click × button or press Delete key
- "Add" button re-enables in sidebar
- Preview thumbnail, name, type, position
- Add/Added button status
- Click card to select item on canvas
- Custom images have × button to remove
- Undo:
Ctrl+Z/Cmd+Z - Redo:
Ctrl+Y/Ctrl+Shift+Z
Works for: add, move, resize, rotate, delete
Redux Toolkit is used for:
- Centralized state (no prop drilling)
- Predictable updates
- Easy undo/redo with history snapshots
- Redux DevTools debugging
- Single slice:
shapesSlice.js - Stores: shapes array, library items, selection, history
- Snapshot-based undo/redo (50 state limit)
- Better performance for frequent updates (drag operations)
- Simpler undo/redo implementation
- Better scalability
- Full support for all actions
- Keyboard shortcuts + header buttons
- 50 state history limit
- Rotate items with transformer
- Rotation-aware boundary detection
- Center position maintained during rotation
- 7 preset images (friends, travel, self-love themes) + 1 rectangle
- Custom image upload
- Add button state management (disabled when placed)
- Bidirectional sync (canvas ↔ sidebar)
- Visual feedback (borders, handles)
- Delete button overlay
- Only selected items can be dragged/resized
- Blob URL handling
- Auto cleanup on removal
- Integrated with library
- React.memo for components
- useCallback for event handlers
- useMemo for expensive computations
- Boundary constraints (works with rotation)
- Minimum size enforcement (20x20)
- Safe deletion (only selected items)
- Multiple items support
- Memory leak prevention (blob cleanup)
src/
├── components/
│ ├── Header/
│ ├── Sidebar/
│ │ └── LibraryCard/
│ └── CanvasArea/
│ └── components/
│ ├── ImageShape/
│ └── DeleteButton/
├── hooks/
│ ├── useKeyboardShortcuts.js
│ └── useCustomImageUpload.js
├── redux/
│ ├── store.js
│ └── slices/shapesSlice.js
├── utils/canvasUtils.js
├── App.js
└── App.css
- React
- Redux Toolkit
- Konva.js / React-Konva
- CSS Modules
Modern browsers (Chrome, Firefox, Edge, Safari - latest versions)