A production-ready full-stack React application demonstrating advanced drag-and-drop functionality, state management, and professional UI/UX design. Users capture photos and decorate them with draggable items on an interactive canvas.
π― Technical Test: Full-Stack Engineer assessment (β 100% requirements + extensive bonus features)
Live Demo: Deploy to Netlify
- Photo Capture (Step 1) - Capture photos via device camera (front/back switching)
- Canvas Display (Step 2) - Photo displayed as background on interactive canvas
- Backend API Endpoint (Step 3) - Jewelry items endpoint using TanStack Start
- Data Fetching (Step 4) - React Query with loading/error states
- Drag & Drop (Step 5) - Full drag-and-drop on canvas with smooth interactions
- β Item Rotation - 15Β° increment controls (Left/Right buttons)
- β Item Resizing - Size constraints (20-200px min/max)
- β Delete Items - Remove from canvas with visual feedback
- β Undo/Redo - Complete edit history with multiple steps
- β Export - Download final composition as high-quality PNG
- β Keyboard Shortcuts - Full keyboard support (Ctrl+Z, Ctrl+Y, Delete, Esc)
- β Accessibility - WCAG 2.1 Level AA compliant
- β Mobile-First Design - Fully responsive (mobile, tablet, desktop)
- β Unit Tests - Component testing with Vitest
- β Error Handling - Graceful error states and user feedback
- β Material Design 3 - Official Google color system (OKLCH color space)
- β Modern Typography - Hierarchical font weights and letter-spacing
- β Animations - Smooth fade-in transitions and micro-interactions
- β Button States - Hover, active, and focus feedback with lift animations
- β Touch Targets - 48px minimum for mobile accessibility (exceeds WCAG AA)
- β Responsive Layouts - Single-row compact edit toolbar on mobile
- β Eye-Friendly Design - Minimal monochrome approach, reduced visual noise
- β Design Tokens - Centralized config system for consistency
- β Visual Hierarchy - Clear spacing and contrast for intuitive navigation
- React 19 - Latest React with modern hooks and concurrent features
- TypeScript - Full type safety (strict mode enabled)
- Tailwind CSS v4 - Modern utility-first CSS framework
- @dnd-kit - Headless drag-and-drop library
- Lucide React - Beautiful SVG icon library
- TanStack Query v5 - Powerful data fetching and caching
- TanStack Router v1 - File-based routing system
- TanStack Start - Full-stack React framework
- Vite - Lightning-fast build tool
- Vitest - Fast unit testing framework
- ESLint & Prettier - Code quality & formatting
- Netlify - Deployment & hosting
- Node.js 18+ or Bun
- npm, yarn, or bun package manager
-
Clone the repository
git clone https://github.com/yourusername/luce-test.git cd luce-test -
Install dependencies
npm install # or yarn install # or bun install
-
Start development server
npm run dev
The app will be available at
http://localhost:3000
- Click "Start Camera" button
- Allow camera permissions when prompted
- Frame your photo and click "Capture Photo"
- Switch cameras (mobile) or retake as needed
Header Controls:
- βΆ Undo - Undo last action (Ctrl+Z)
- β· Redo - Redo last action (Ctrl+Y)
- Retake - Go back to camera to capture new photo
- β¬οΈ Export - Download your finished creation
Decorating Items:
- Drag jewelry pieces from the sidebar onto your photo
- Click any item to select it
- Edit selected item using the toolbar below the photo:
- Rotate Left / Rotate Right - Rotate item (15Β° steps)
- Smaller / Larger - Resize item (constrained: 40-200px)
- Delete - Remove item from canvas
- Drag to move selected or unselected items around the photo
Layout (Mobile vs Desktop):
- Mobile: Edit toolbar displays in single row (compact, 48px touch targets)
- Tablet: Buttons scale responsively with
text-sm - Desktop: Full spacing with
text-baseand responsive gaps
Keyboard shortcuts:
Ctrl+Z/Cmd+Z- UndoCtrl+Y/Ctrl+Shift+Z- RedoDelete/Backspace- Remove selected itemEsc- Deselect current item
- React hooks + custom hooks for local state (simpler than Redux for this scope)
- useCanvasHistory for undo/redo with full state snapshots
- React Query for server state (items API) with intelligent caching
- @dnd-kit chosen for headless, keyboard-accessible drag-and-drop
- Pointer sensor with 5px activation distance (prevents accidental drags on click)
- Proper coordinate calculation accounting for canvas position and item centering
- Material Design 3 with OKLCH colors - Perceptually uniform color space
- CSS-first Tailwind v4 - Future-proof, theme-based configuration
- Centralized config (
canvasConfig.ts) - Single source of truth for magic numbers - Touch-first mobile design - 48px minimum buttons (exceeds WCAG AA 44px requirement)
- React.memo for drag-and-drop item components (prevents unnecessary re-renders)
- Debounced canvas resize tracking (100ms) - smooth experience without lag
- Lazy loading of components with React.lazy and Suspense (if needed)
- Optimized exports - Canvas to PNG at full resolution efficiently
- Responsive typography - text-xs (mobile) β text-sm (tablet) β text-base (desktop)
- Responsive padding - px-1 (mobile) β px-2 (tablet) β px-4 (desktop)
- Single-row edit toolbar - All 5 controls fit on mobile with minimal padding
- Touch-friendly spacing - Gap-1 (4px) between buttons on mobile
src/
βββ components/
β βββ Canvas.tsx # Main canvas editor component
β βββ Canvas.test.tsx # Canvas component tests
β βββ PhotoCapture.tsx # Camera capture component
β βββ PhotoCapture.test.tsx # PhotoCapture tests
βββ hooks/
β βββ useCanvasHooks.ts # Custom hooks for canvas operations
βββ routes/
β βββ __root.tsx # Root layout
β βββ index.tsx # Main app page
β βββ api/
β βββ items.ts # API endpoint for jewelry items
βββ utils/
β βββ items.ts # Jewelry item data & fetch logic
βββ router.tsx # Router configuration
βββ styles.css # Global styles & accessibility
βββ env.ts # Environment variable validation
- Main editor interface with responsive layout
- Header row: Title + Undo/Redo/Retake/Export controls
- Canvas display: Photo with draggable items overlay
- Edit toolbar: Rotation, resize, delete (3 rows on mobile, 1 row on desktop)
- Drag-and-drop management with @dnd-kit
- Item manipulation (rotate, resize, delete)
- Undo/redo history with full state snapshots
- Export to PNG functionality
- Full keyboard shortcut support
- Camera access via WebAPI
- Front/back camera switching
- Photo capture to data URL
- Error handling
- Mobile-friendly UI
- useCanvasHistory() - Manages undo/redo state
- useCanvasSize() - Tracks photo dimensions
- useKeyboardShortcuts() - Handles keyboard input
- useItemOperations() - Rotation, resize, delete logic
- useExportImage() - Canvas to PNG export
- β Chrome/Edge 90+
- β Firefox 88+
- β Safari 14+
- β Mobile browsers (iOS Safari, Chrome Mobile)
- Lazy loaded components with React.memo
- Optimized drag-and-drop with debounced resize tracking
- Efficient state management with React Query caching
- Asset optimization via Vite
- Responsive images with native img element
MIT License - feel free to use for personal and commercial projects
Contributions are welcome! Please feel free to submit a Pull Request.
Built with:
- TanStack ecosystem
- Tailwind CSS
- @dnd-kit
- React
- Vite
**Made with π by Mehdi
Last Updated: November 2025