# Phase 2 — React UI Components Task Spec ## Context - Project: web-cad-neu (clean rewrite of web-cad) - Frontend: /a0/usr/workdir/web-cad-neu/frontend/ - Stack: React 18 + TypeScript + Vite, plain CSS (no Tailwind/styled-components) - tsconfig: jsx=react-jsx, baseUrl=./src, paths @/* -> . ## Reference Files (READ THESE FIRST) - Mockup HTML: /a0/usr/workdir/web-cad-neu/mockup/editor.html (1133 lines) - Mockup theme CSS: /a0/usr/workdir/web-cad-neu/mockup/assets/styles.css (195 lines) - Mockup layout CSS: /a0/usr/workdir/web-cad-neu/mockup/assets/layout.css (1298 lines) - Types: /a0/usr/workdir/web-cad-neu/frontend/src/types/cad.types.ts - Phase 1 engines: /a0/usr/workdir/web-cad-neu/frontend/src/canvas/*.ts, /a0/usr/workdir/web-cad-neu/frontend/src/interaction/index.ts ## Output Directory /a0/usr/workdir/web-cad-neu/frontend/src/ ## Files to Create (15 components + 1 CSS) ### 1. styles.css - Copy /a0/usr/workdir/web-cad-neu/mockup/assets/styles.css + layout.css content into ONE file at frontend/src/styles.css - Keep all CSS class names verbatim from mockup - Keep all CSS variables from styles.css - Add mobile breakpoint rules from layout.css (<=768px) ### 2. App.tsx - Root component: imports styles.css - Layout:
> Topbar + RibbonBar +
> LeftSidebar + CanvasArea + RightSidebar +
+ CommandLine + StatusBar + MobileDrawers - State: activeTool, activeRibbonTab, activeRightPanel, theme, snapEnabled, orthoEnabled, gridEnabled, selectedElements, layers, cursorPos, commandHistory - Pass props to children ### 3. components/Topbar.tsx - class="topbar" with topbar-left (hamburger, logo, app-name, project-name, saved-badge) and topbar-right (undo, redo, divider, versions, share, divider, theme-toggle, help, divider, lang-select, notifications, avatar) - Copy SVG icons EXACTLY from mockup lines 21-68 - Props: projectName, savedStatus, onUndo, onRedo, onThemeToggle, theme ### 4. components/RibbonBar.tsx - class="ribbon" with ribbon-tabs (6 tabs: Start/Einfügen/Format/Ansicht/Extras/KI) + ribbon-content - Start tab groups: Datei (Neu/Öffnen/Speichern), Bearbeiten (Undo/Redo/Kopieren/Einfügen), Ansicht (Zoom Fit/100%/Grid/Layer), Extras (Messen/Suchen/KI/Plugins) - Copy SVGs from mockup lines 72-191 - Props: activeTab, onTabChange, onAction ### 5. components/LeftSidebar.tsx - class="leftbar" with header (title + toggle), 4 tool-sections, footer (3 buttons) - Sections: Auswählen/Anzeigen (Auswahl/Pan/Zoom/Messen), Zeichnen (Linie/Polylinie/Rechteck/Kreis/Bogen/Text/Bemaßung/Schraffur), Bearbeiten (Move/Copy/Rotate/Scale/Mirror/Trim/Offset/Löschen), Bestuhlung (Reihe/Block/Tisch/Bühne) - 20 tool buttons with data-tool, title, SVG icon, label, kbd shortcut - Copy SVGs from mockup lines 198-360 - Props: activeTool, onToolChange - Footer: Plugin/Settings/Help buttons ### 6. components/CanvasArea.tsx - class="canvas-area" with canvas-coords (X/Y display), canvas-view-tabs (2D/ISO/Front/Top), element (NOT SVG) - useEffect: init RenderEngine + ZoomPanController + InteractionEngine on canvas ref - Floating toolbar: zoom in/out/fit, grid toggle, ortho toggle, snap toggle, prev view - Props: cursorPos, viewMode, onViewChange, gridEnabled, orthoEnabled, snapEnabled, onToggleGrid, onToggleOrtho, onToggleSnap, onZoomIn, onZoomOut, onZoomFit ### 7. components/RightSidebar.tsx - class="rightbar" with rightbar-tabs (Werkzeug/Layer/Bibliothek/KI) + rightbar-content - Tab switching shows/hides panels - KI tab has badge (count) - Copy SVGs from mockup lines 669-687 - Props: activePanel, onPanelChange, selectedElement, layers, blocks ### 8. components/PropertiesPanel.tsx - rightbar-panel data-panel-content="tool" - Sections: selection info, Geometrie (X/Y/Breite/Tiefe/Drehung inputs), Darstellung (Farbe color picker+hex, Linientyp select, Stärke select, Layer select), Block (name+description inputs) - Copy structure from mockup lines 692-776 - Props: selectedElement, layers, onUpdateProperty ### 9. components/LayerPanel.tsx - rightbar-panel data-panel-content="layer" - Uses TreeView component for layer hierarchy - Header with options button + add-layer button - Copy structure from mockup lines 779-866 - Props: layers, onSelectLayer, onAddLayer, onToggleLayer ### 10. components/BlockLibrary.tsx - rightbar-panel data-panel-content="library" - lib-search (input with search icon), lib-categories (Alle/Bestuhlung/Tische/Bühne/Deko chips), tree-library with draggable items - Copy structure from mockup lines 897-976 - Props: blocks, category, onCategoryChange, onSearch, onDragBlock ### 11. components/KICopilot.tsx - rightbar-panel data-panel-content="ki" - ki-header (avatar, title, status), ki-suggestions (chips), ki-chat (messages), ki-input-wrap (input+voice+send) - Copy structure from mockup lines 978-1026 - Props: messages, suggestions, onSend, onSuggestionClick ### 12. components/CommandLine.tsx - class="cmdline" with cmdline-history (entries with prefix · or ›) + cmdline-input-wrap (prompt › + input) - Copy structure from mockup lines 1076-1089 - Props: history, onCommand ### 13. components/StatusBar.tsx - class="statusbar" with status-items: SNAP/ORTHO/POLAR/GRID toggles, X/Y coords, active layer, active tool, online status - Copy structure from mockup lines 1092-1127 - Props: snapEnabled, orthoEnabled, polarEnabled, gridEnabled, cursorX, cursorY, activeLayer, activeTool, onlineCount, onToggleSnap, onToggleOrtho, onTogglePolar, onToggleGrid ### 14. components/TreeView.tsx - Reusable tree component for LayerPanel and BlockLibrary - Props: nodes (TreeNode[]), onSelect, onToggle, draggable, renderIcon - TreeNode type: { id, name, count?, icon?, children?, expanded?, active?, draggable? } - Renders tree-node > tree-row (tree-row-folder or tree-row-leaf) > tree-children recursively ### 15. components/MobileDrawers.tsx - Scrim + drawer-left + drawer-right - drawer-left: header (title + close) + body (filled with LeftSidebar content) - drawer-right: header (title + close) + drawer-tabs (Wz/Layer/Lib/KI) + body - Copy structure from mockup lines 1032-1073 - Props: leftOpen, rightOpen, activeRightTab, onCloseLeft, onCloseRight, onRightTabChange ## Rules - TypeScript functional components with React.FC or function syntax - NO inline styles except where mockup uses them (style="...") - NO styled-components, NO Tailwind - Import styles.css once in App.tsx - Copy SVG icons EXACTLY from mockup (viewBox, paths, attributes) - Use mockup CSS class names verbatim - All text in German (matching mockup) - CanvasArea uses not — wire to Phase 1 engines - Mobile breakpoint <=768px: hamburger shows, sidebars hide, drawers slide in - npx tsc --noEmit must pass with zero errors - Each component in its own file under components/