Skip to content

feat(ui): redesign phase 3 — canvas view modes, tools and options bar - #28

Merged
provos merged 2 commits into
mainfrom
feat/redesign-canvas
Sep 26, 2026
Merged

provos merged 2 commits into
mainfrom
feat/redesign-canvas

Conversation

@provos

@provos provos commented Sep 26, 2026

Copy link
Copy Markdown
Owner

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)

  • The bar offers Input · Depth · Slice · Composite · Parallax 2D · 3D, plus the Checkerboard toggle and zoom (− / % / + / Fit).
  • Input and Parallax 2D show the server's display image, exactly as before: the input, a SAM preview, the selected slice's highlight, or the latest camera render. The existing pixel checks against main-image therefore still hold.
  • Depth, Slice (the selected slice on a checkerboard) and Composite (all slices, ground first then far to near, the order the reference render uses) are drawn in the browser from existing assets.
  • Entering Parallax 2D renders the reference view, unless a camera render is already showing.
  • 3D replaces the old 2D/3D tabs.

Tools (CanvasToolbar)

  • Pan (H), Segment (S), Brush (B), Extend (O, planned, disabled) and Horizon (G).
  • Clicking the image segments only with Segment. The mask canvas paints only with Brush, and the horizon line appears only with Horizon. Middle-drag always pans.
  • Picking a tool moves the workflow to that tool's step. Each step sets its default view and tool (HANDOFF §4); for example, Inpaint opens the Slice view with the Brush.

Tool options (ToolOptionsBar)

  • Segment: Select by Object / Depth band replaces the Mode Selector, and Object (SAM) is now the default (HANDOFF goal 7). Multi-point, "Segment N points", Invert and Feather.
  • Brush: Clear / Erase / Load / size. Horizon: row and pitch. Parallax 2D: the camera pad.

Empty state and upload

  • With no image, the canvas shows Choose image… and load a saved project…. Dropping an image still works at any time.
  • The canvas no longer opens the file chooser on a click once an image is loaded.

Tests

  • vitest:
    • InputImagePanel tests reduced to the stage (pixel math, modifiers, guards, zoom/pan, empty state, horizon).
    • New ToolOptionsBar, ViewModeBar, CanvasToolbar and CanvasArea tests.
    • Store tests for the step/view/tool rules.
  • e2e:
    • The driver picks the tool or view an action needs.
    • New UiDriver.canvasImage() for geometry checks: the image box shared by every view, which follows zoom/pan.
    • The two specs that relied on the old Depth Map default now set it explicitly, and one also asserts the new Object default.
  • Results: vitest 237 passed, svelte-check 0 errors / 0 warnings, e2e 46/46.
  • Screenshots checked on the lighthouse project for every step's default view.

Next: phase 4, the SAM-first SegmentPanel and SelectionBar, including the rest-of-image slice.

🤖 Generated with Claude Code

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>
Copilot AI lite review requested due to automatic review settings September 26, 2026 06:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

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/CanvasTool state in uiStore with 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.

Comment on lines +7 to +14
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';

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 189 to 193
resetSession(): void {
inpainted = false;
previewed = false;
exported = false;
step = 'image';

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@provos
provos merged commit ccbeba4 into main Sep 26, 2026
1 check passed
@provos
provos deleted the feat/redesign-canvas branch September 26, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants