Skip to content

Fix UI Builder shift-click resize without drag#6

Merged
zeidalidiez merged 1 commit into
mainfrom
fix/ui-builder-shift-click-resize
Jul 10, 2026
Merged

Fix UI Builder shift-click resize without drag#6
zeidalidiez merged 1 commit into
mainfrom
fix/ui-builder-shift-click-resize

Conversation

@zeidalidiez

@zeidalidiez zeidalidiez commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

Shift-clicking a selected layer on the UI Builder canvas to resize (without dragging) could shrink it to the minimum size and made recovery hard.

Causes

  1. Generic corner handle applied left and right (and top and bottom) in one update, so a click near a corner collapsed width/height to 8px.
  2. No drag threshold — any micro-movement applied resize and still committed undo history.

Fix

  • Distinct corner handles: nw / ne / sw / se
  • Resize always computed from geometry at mousedown
  • Gestures only apply after DRAG_THRESHOLD_PX (3px) of movement; click-in-place is a no-op and does not push history
  • Pure helpers in builderResize.ts with unit tests

Test plan

  • pnpm --filter cli test (includes new resize unit tests)
  • pnpm --filter web lint
  • Manual: select a layer, shift-click a corner/edge without moving → size unchanged
  • Manual: shift-drag a corner/edge → resizes correctly from that handle only
  • Manual: undo still works after a real resize drag

Greptile Summary

This PR fixes UI Builder resize gestures so shift-clicks do not resize selected layers. The main changes are:

  • Adds pure resize helpers for directional edge and corner handles.
  • Computes resize bounds from the geometry captured at mouse down.
  • Applies move and resize updates only after a small drag threshold.
  • Skips undo-history entries for click-only interactions.
  • Adds unit tests for handle detection, minimum-size clamping, and click-in-place behavior.

Confidence Score: 5/5

Safe to merge with low risk.

The resize change is narrow, uses shared pure helpers, and has focused tests for the fixed behavior.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Observed the initial selection geometry as x=80, y=80, width=140, height=80 and noted Undo (1) is available.
  • Recorded the southeast shift-drag resize, which updated the geometry to width=224 and height=144 and exposed Undo (2).
  • After performing Undo, the geometry was restored to width=140 and height=80, with all assertions remaining true.
  • Verified the Playwright resize script completed with exit code 0 as shown in the ui-builder-resize-playwright.log.
  • Linked and summarized the uploaded artifacts to support review of the resize sequence, including the results JSON, videos, and sequence images.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
apps/web/src/UIBuilder.tsx Updates canvas interaction state to apply move/resize only after a drag threshold and commit undo history only for real drags; no issues found.
apps/web/src/builderResize.ts Adds pure resize helpers with distinct edge/corner handles, minimum-size clamping, and origin-based geometry calculations; no issues found.
apps/cli/tests/ui-builder-resize.test.ts Adds unit coverage for distinct resize handles, click-in-place behavior, clamping, and drag-threshold constants; no issues found.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant UI as UIBuilder
participant Helpers as builderResize
participant State as Builder state/history

User->>UI: mouseDown on selected layer with Shift
UI->>Helpers: getResizeHandle(layer, mx, my)
Helpers-->>UI: directional handle or null
UI->>UI: store origin geometry and pointer start
User->>UI: mouseMove
UI->>UI: compare movement with DRAG_THRESHOLD_PX
alt movement below threshold
    UI-->>State: no geometry or history update
else real drag
    UI->>Helpers: applyResizeHandle(handle, origin, pointer, snap)
    Helpers-->>UI: new bounds
    UI->>State: update selected layer geometry
end
User->>UI: mouseUp
alt didDrag
    UI->>State: push pre-gesture state to history
else click only
    UI-->>State: no history entry
end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant UI as UIBuilder
participant Helpers as builderResize
participant State as Builder state/history

User->>UI: mouseDown on selected layer with Shift
UI->>Helpers: getResizeHandle(layer, mx, my)
Helpers-->>UI: directional handle or null
UI->>UI: store origin geometry and pointer start
User->>UI: mouseMove
UI->>UI: compare movement with DRAG_THRESHOLD_PX
alt movement below threshold
    UI-->>State: no geometry or history update
else real drag
    UI->>Helpers: applyResizeHandle(handle, origin, pointer, snap)
    Helpers-->>UI: new bounds
    UI->>State: update selected layer geometry
end
User->>UI: mouseUp
alt didDrag
    UI->>State: push pre-gesture state to history
else click only
    UI-->>State: no history entry
end
Loading

Reviews (1): Last reviewed commit: "Fix UI Builder shift-click resize collap..." | Re-trigger Greptile

Shift-click near a corner used a generic 'corner' handle that applied
both left and right (and top and bottom) in one move, shrinking the
layer to the 8px minimum. Use directional corner handles, compute
resize from mousedown origin geometry, and ignore gestures that never
cross a small drag threshold so a click-in-place is a no-op.
@zeidalidiez zeidalidiez merged commit 43415df into main Jul 10, 2026
2 checks passed
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.

1 participant