Repository navigation
feat(ui): redesign phase 3 — canvas view modes, tools and options bar - #28
Conversation
HANDOFF.md §12 step 3: - ViewModeBar: Input, Depth, Slice, Composite, Parallax 2D, 3D, plus the checkerboard toggle and zoom (-, %, +, Fit). Input and Parallax 2D show the server's display image; Depth, Slice (the selected slice on a checkerboard) and Composite (all slices, ground first then far to near) are drawn client-side. Entering Parallax 2D renders the reference view unless a camera render is already showing. - CanvasToolbar floating over the canvas: Pan, Segment, Brush, Extend (planned, disabled) and Horizon. Clicks segment only with Segment, the mask canvas paints only with Brush, the horizon line shows with Horizon. - ToolOptionsBar: Segment's Select by Object / Depth band (replacing the Mode Selector; Object is the default), Multi-point and Segment N points, Invert, Feather; Brush options; horizon row and pitch; the camera pad in Parallax 2D. - Steps set their default view and tool; picking a tool moves to its step. - The stage opens the file chooser only from the empty state (Choose image / load a saved project); drops still upload. - e2e: the driver picks the tool or view an action needs; canvasImage() for geometry checks; specs that relied on the old Depth Map default set it explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
A per-project render-tracking value is not cleared on new-session reset, and the new ARIA tablist lacks proper roving-tabindex/keyboard behavior, both of which should be addressed before approval.
Review effort: Lite
Findings: 2
Open (2)
What changed in this PR
Implements phase 3 of the Svelte UI redesign by replacing the legacy “controls under the image” + 2D/3D tabs with a dedicated canvas column composed of a view-mode bar, floating tool palette, and context-sensitive tool options bar. This refactors how the canvas is driven (view/tool/step rules) while keeping segmentation, inpainting mask editing, parallax preview, and 3D viewing accessible through the new affordances.
Changes:
- Introduces
CanvasView/CanvasToolstate inuiStorewith step→(view,tool) defaults and tool→step/view routing. - Replaces the old viewer tab layout with
CanvasArea(ViewModeBar + ToolOptionsBar + stage + 3D viewer) and updates the canvas stage to render Depth/Slice/Composite views client-side. - Updates vitest/e2e coverage and drivers to operate through the new view/tool controls (including geometry checks via
canvasImage()).
| File | Description |
|---|---|
| frontend/src/lib/workflow.ts | Records the last camera-rendered mainImage URL after camera navigation. |
| frontend/src/lib/state/ui.svelte.ts | Adds CanvasView/CanvasTool, step defaults, tool routing, and render-tracking state. |
| frontend/src/lib/state/ui.svelte.test.ts | New unit tests for step/view/tool defaulting and routing behavior. |
| frontend/src/lib/components/viewer/Model3DViewer.svelte | Switches lazy-load trigger from old viewer tabs to uiStore.view === '3d'. |
| frontend/src/lib/components/viewer/Model3DViewer.test.ts | Updates tests to use uiStore.view instead of viewerTab. |
| frontend/src/lib/components/upload/ViewerTabs.svelte | Removed old 2D/3D viewer tab UI. |
| frontend/src/lib/components/upload/ViewerTabs.test.ts | Removed tests for the deleted viewer tabs component. |
| frontend/src/lib/components/upload/InputImagePanel.svelte | Reworks the canvas stage: empty state, view-driven rendering, zoom/pan, tool-gated interactions, local Depth/Slice/Composite rendering. |
| frontend/src/lib/components/upload/InputImagePanel.test.ts | Refactors tests to the new stage behavior (tool gating, empty state, zoom/pan, horizon tool). |
| frontend/src/lib/components/shell/AppShell.svelte | Replaces ViewerTabs usage with CanvasArea. |
| frontend/src/lib/components/export/ExportTab.svelte | Updates comment reference from ViewerTabs to Model3DViewer. |
| frontend/src/lib/components/depth/ModeTab.svelte | Removes the old “Mode Selector” UI (segmentation mode moved to tool options). |
| frontend/src/lib/components/canvas/ViewModeBar.svelte | New view-mode + checkerboard + zoom bar. |
| frontend/src/lib/components/canvas/ViewModeBar.test.ts | New tests for view availability, checkerboard toggle, and zoom controls. |
| frontend/src/lib/components/canvas/ToolOptionsBar.svelte | New tool options bar (Segment/Brush/Horizon/Parallax camera pad/3D hint). |
| frontend/src/lib/components/canvas/ToolOptionsBar.test.ts | New tests for tool options behavior and API interactions. |
| frontend/src/lib/components/canvas/CanvasToolbar.svelte | New floating tool palette (Pan/Segment/Brush/Extend disabled/Horizon). |
| frontend/src/lib/components/canvas/CanvasToolbar.test.ts | New tests for tool palette enablement and selection behavior. |
| frontend/src/lib/components/canvas/CanvasArea.svelte | New canvas column composition + Parallax “enter view” camera-reset behavior. |
| frontend/src/lib/components/canvas/CanvasArea.test.ts | New tests for Parallax entry camera-reset behavior keyed off renderedMainUrl. |
| frontend/src/lib/components/canvas/MaskToolbar.svelte | Repositions/renames documentation to reflect Brush tool options bar usage. |
| frontend/src/lib/components/canvas/MaskCanvas.svelte | Gates interactivity/visibility by tool/view instead of Inspector tab. |
| e2e/ux-parity.spec.ts | Updates geometry assertions to use ui.canvasImage() and explicit segmentation mode setting. |
| e2e/parallax-maker.spec.ts | Updates segmentation-mode assumptions (Object default; depth-band explicitly selected). |
| e2e/layout.spec.ts | Updates geometry assertions to use ui.canvasImage(). |
| e2e/drivers/types.ts | Adds canvasImage() to the UiDriver interface for zoom/pan-following geometry checks. |
| e2e/drivers/svelte.ts | Implements canvasImage(), adds tool/view selection helpers, and updates flows for new UI. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| import Minus from '@lucide/svelte/icons/minus'; | ||
| import Plus from '@lucide/svelte/icons/plus'; | ||
| import Grid2x2 from '@lucide/svelte/icons/grid-2x2'; | ||
| import { uiStore, CANVAS_VIEWS } from '../../state/ui.svelte'; | ||
| import { projectStore } from '../../state/project.svelte'; | ||
| import { viewportStore } from '../../state/viewport.svelte'; | ||
| import { isBusy } from '../../state/busy.svelte'; | ||
| import * as workflow from '../../workflow'; |
There was a problem hiding this comment.
Fixed: the view-mode tabs now use the shared rovingTabs action with a roving tabindex. rovingTabs now skips disabled tabs, since this strip has them. A test covers it.
| resetSession(): void { | ||
| inpainted = false; | ||
| previewed = false; | ||
| exported = false; | ||
| step = 'image'; |
There was a problem hiding this comment.
Fixed: resetSession() now clears renderedMainUrl; the store test asserts it.
…render URL - The view-mode tabs get a roving tabindex and arrow/Home/End keys, which now skip disabled tabs. - resetSession() forgets the last camera render's URL, so a new project's first Parallax 2D visit always renders the reference view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Phase 3 of the UI redesign (docs/redesign/HANDOFF.md, §12 step 3). The controls under the image are replaced by a view-mode bar, a floating tool palette and a tool-options bar.
View modes (
ViewModeBar)main-imagetherefore still hold.Tools (
CanvasToolbar)Tool options (
ToolOptionsBar)Empty state and upload
Tests
InputImagePaneltests reduced to the stage (pixel math, modifiers, guards, zoom/pan, empty state, horizon).ToolOptionsBar,ViewModeBar,CanvasToolbarandCanvasAreatests.UiDriver.canvasImage()for geometry checks: the image box shared by every view, which follows zoom/pan.Next: phase 4, the SAM-first
SegmentPanelandSelectionBar, including the rest-of-image slice.🤖 Generated with Claude Code