---
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

<!-- SECTION:DESCRIPTION:BEGIN -->
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.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [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
<!-- AC:END -->

## Final Summary

<!-- SECTION:FINAL_SUMMARY:BEGIN -->
## 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
<!-- SECTION:FINAL_SUMMARY:END -->
