--- id: TASK-68 title: 'Canvas toolbar popout, click-to-place, double-click edit, SVG persistence' status: Done assignee: [] created_date: '2026-02-28 00:26' updated_date: '2026-02-28 00:26' labels: - canvas - ux - toolbar dependencies: [] priority: medium --- ## Description Canvas UX improvements: toolbar popout panel replaces inline dropdowns, click-to-place shapes at cursor position, double-click to edit shapes, whiteboard SVG drawing persistence via Automerge, + button opens rApps, dblclick canvas for pencil mode. ## Acceptance Criteria - [x] #1 Toolbar group click opens popout panel to the right (not inline dropdown) - [x] #2 Click toolbar tool → cursor changes to crosshair → click canvas → shape at click position - [x] #3 Shape avoids overlapping existing shapes (spiral search from click point) - [x] #4 Double-click shape → edit mode → can type/interact with content - [x] #5 Double-click empty canvas → pencil draw mode activates - [x] #6 Draw with pencil → reload → drawings persist (wb-svg in Automerge) - [x] #7 Click + button → rApp list opens in popout panel - [x] #8 Reload page → all shapes retain x,y positions - [x] #9 bunx tsc --noEmit passes ## Final Summary ## Changes ### Toolbar Popout Panel (canvas.html CSS/HTML/JS) - Added `#toolbar-panel` with header + body positioned right of `#toolbar` - Group toggles populate the popout panel via `openToolbarPanel()`/`closeToolbarPanel()` - Inline `.toolbar-dropdown` hidden with `display: none !important` when group is open - Mobile: panel slides up from bottom as a sheet ### Click-to-Place (canvas.html) - `pendingTool` state with `setPendingTool()`/`clearPendingTool()` - All toolbar buttons set pending tool instead of calling `newShape()` directly - Canvas `pointerdown` checks `pendingTool`, converts screen→canvas coords, places shape - Ghost outline (dashed teal) follows cursor while tool is pending; ESC cancels - `findFreePosition(width, height, preferX?, preferY?)` refactored to accept anchor point ### Double-Click Edit Mode (folk-shape.ts) - `enterEditMode()`/`exitEditMode()` with `:state(editing)` internal state - CSS: editing state enables `pointer-events: auto` on `.slot-container`, teal outline - `dblclick` listener on shape calls `enterEditMode()`, focuses first focusable child - Canvas background click calls `exitEditMode()` on all shapes ### Click-to-Edit Markdown (folk-markdown.ts) - Preview area click enters edit mode - `edit-enter`/`edit-exit` custom events sync with parent shape editing state - Refactored into `enterMarkdownEdit()`/`exitMarkdownEdit()` helpers ### + Button Opens rApps (canvas.html) - `#quick-add` button at top of toolbar opens rApps group in popout panel - Mobile FAB first tap auto-opens rApps panel ### SVG Drawing Persistence (community-sync.ts + canvas.html) - `addShapeData()` method on CommunitySync for DOM-less shapes - `wb-svg` type: SVG serialized on pointerup, stored in Automerge, recreated on load - Eraser removes from both DOM and Automerge doc ### Canvas dblclick → Pencil Mode - dblclick on empty canvas background activates pencil drawing tool ### Files Modified - `website/canvas.html` — toolbar panel, click-to-place, findFreePosition, +button, SVG persistence, dblclick - `lib/folk-shape.ts` — dblclick→editing state, enterEditMode/exitEditMode, CSS - `lib/folk-markdown.ts` — click-to-edit preview, edit-enter/exit events - `lib/community-sync.ts` — svgMarkup field, addShapeData() method ### Commits - `eee9cbe` — shape overlap push-aside, coordinate persistence, toolbar panel clipping - `645f1fc` — SVG drawing persistence, click-to-edit markdown, quick-add rApps, dblclick pencil