Skip to content

feat(ui): redesign phase 2 — layer panel with depth ruler - #27

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

provos merged 2 commits into
mainfrom
feat/redesign-layers

Conversation

@provos

@provos provos commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Phase 2 of the UI redesign (docs/redesign/HANDOFF.md, §12 step 2). The slice thumbnail strip is replaced by an always-visible layer panel.

What changes

  • LayerPanel (left column, 300px):
    • Slices are listed nearest first, each with a thumbnail, name, a GROUND badge and a depth chip.
    • Clicking a row selects its slice; clicking the selected row deselects it.
    • Clicking a row's depth chip edits that slice's depth in place, without selecting it.
    • Delete (or Backspace) while the list has focus deletes the selected slice.
    • Copy / Paste / Delete move to the panel header. As before, they stay enabled and log a message when their precondition is missing, rather than being disabled.
    • An empty state explains how to create layers.
  • DepthRuler:
    • A 255 (near) to 0 (far) axis with a handle per slice, linked to its row by a curve. The ground handle is green, the selected one blue.
    • Dragging a handle, or pressing ↑/↓ (Shift ×10) on a focused one, previews the depth and commits setSliceDepth on release.
  • SelectedSliceHeader at the top of the Inspector shows the selected slice, with Download and Replace image…. Per the design, these replace the per-thumbnail download link and drop target.
  • The Segmentation panel no longer has the slice strip, and the Inspector narrows from 440px to 360px.

Tests

  • vitest:
    • New LayerPanel.test.ts (19 tests), ported from the old strip tests plus new ones: nearest-first order, empty state, Delete key, ruler keyboard nudge and pointer drag.
    • New SelectedSliceHeader.test.ts (5 tests).
    • SegmentationTab.test.ts trimmed accordingly.
    • A ResizeObserver stub for jsdom.
  • e2e: slices are addressed by index through a new UiDriver.sliceImage(i), since display order is now nearest first. Undo/redo use the header's buttons for the selected slice, and download and replace select the slice first.
  • Results: vitest 186 passed, svelte-check 0 errors / 0 warnings, e2e 46/46.
  • Screenshots checked at 1440×900 and 1280×800 on the lighthouse project.

Next: phase 3, canvas view modes and tools.

🤖 Generated with Claude Code

HANDOFF.md §12 step 2:

- LayerPanel: always-visible layer list, nearest first, with thumbnail,
  name, GROUND badge and a depth chip that edits depth in place (without
  selecting). Click selects/deselects; Delete on the focused list deletes
  the selected slice. Copy / Paste / Delete move to its header.
- DepthRuler: 255 (near) to 0 (far) axis with a handle per slice linked
  to its row (ground green, selected blue); drag or arrow keys preview
  locally and commit setSliceDepth on release.
- SelectedSliceHeader at the top of the Inspector: the selected slice
  with Download and Replace image.
- The slice strip and its Copy/Paste/Delete are gone from the
  Segmentation panel; the Inspector narrows to 360px.
- e2e: slices are addressed by index (sliceImage(i)), undo/redo use the
  header for the selected slice, download/replace select the slice first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 06:32

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

The new in-place depth editing in LayerPanel can commit out-of-range depths (negative/>255), which can break ruler mapping and produce unexpected backend state.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Implements phase 2 of the Svelte UI redesign by introducing an always-visible LayerPanel (with a DepthRuler) and moving selected-slice affordances into a new SelectedSliceHeader, while removing the legacy slice thumbnail strip from the Segmentation tab. This aligns slice selection, depth editing, undo/redo, download, and replace-image flows with the redesign handoff.

Changes:

  • Add LayerPanel + DepthRuler for nearest-first slice listing and depth editing (drag + keyboard), and adjust app layout columns.
  • Add SelectedSliceHeader in the Inspector to centralize per-slice download/replace actions.
  • Update unit tests and Playwright E2E driver/specs to use the new UI structure and slice addressing.
File Description
frontend/​src/​setupTests.ts Adds a jsdom ResizeObserver stub for components using bind:clientHeight.
frontend/​src/​lib/​components/​shell/​Inspector.svelte Renders SelectedSliceHeader above Inspector sections (non-Configuration tabs).
frontend/​src/​lib/​components/​shell/​AppShell.svelte Adds LayerPanel to the main grid and adjusts column widths/breakpoints.
frontend/​src/​lib/​components/​segmentation/​SegmentationTab.test.ts Removes/updates tests tied to the removed slice strip and relocated actions.
frontend/​src/​lib/​components/​segmentation/​SegmentationTab.svelte Removes the slice thumbnail strip UI and related handlers/styles; simplifies layout.
frontend/​src/​lib/​components/​layers/​SelectedSliceHeader.test.ts Adds unit coverage for selected-slice header rendering, download, and replace flow.
frontend/​src/​lib/​components/​layers/​SelectedSliceHeader.svelte Implements the Inspector header for the selected slice (thumb, depth, ground, download/replace).
frontend/​src/​lib/​components/​layers/​LayerPanel.test.ts Adds unit coverage for ordering, empty state, selection toggle, depth chip edit, header actions, delete key, and ruler interactions.
frontend/​src/​lib/​components/​layers/​LayerPanel.svelte Implements the new layer list UI, selection semantics, in-place depth editing, and wiring to DepthRuler.
frontend/​src/​lib/​components/​layers/​DepthRuler.svelte Adds the vertical 255→0 ruler with draggable/keyboard-adjustable handles and commit-on-release behavior.
e2e/​slice-editing.spec.ts Switches slice thumbnail targeting to ui.sliceImage(i) under nearest-first display order.
e2e/​parallax-maker.spec.ts Updates slice thumbnail access to the new sliceImage(i) helper while preserving count checks.
e2e/​drivers/​types.ts Extends UiDriver with sliceImage(index) and clarifies semantics around undo/redo targeting.
e2e/​drivers/​svelte.ts Implements sliceImage(index), updates selection logic for the new panel, and routes undo/redo/download/replace via the selected-slice header.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +67 to +74
function commitDepth(index: number): void {
if (editingIndex !== index) return;
editingIndex = null;
// Blank or non-integer input does not commit (it must not become 0).
const draft = depthDraft.trim();
if (!/^-?\d+$/.test(draft)) return;
void workflow.setSliceDepth(index, Number.parseInt(draft, 10));
}

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: typed depths are now clamped to 0–255 before setSliceDepth (blank and non-integer input still don't commit). Added tests for 300 → 255 and -5 → 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@provos
provos merged commit 65a4738 into main Sep 26, 2026
1 check passed
@provos
provos deleted the feat/redesign-layers branch September 26, 2026 06:47
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