fix(rotate): selection box rotates with shape during rotate drag#40
Merged
Conversation
Previously `doRotate` rebuilt the handles via `showResizeHandles(shapes)` every frame, producing a growing/shrinking axis-aligned AABB instead of a tight box tracking the shape's rotation. Snapshot handle origins at `startRotate` and apply the delta rotation around the selection center on each frame; snap back to the AABB on release so the next corner resize anchors correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Map each handle to a data-option value in doPointerMove so the CSS cursor reflects the affordance: nwse-resize / nesw-resize for corners, grab for the rotate handle. Clear the option when leaving the pointer tool so a stale hover state doesn't survive tool switches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend the hover-cursor logic so the cursor shows grab when the mouse is over a selected shape's bbox or inside the group outline (and not over a resize/rotate handle, which keep priority). Makes the move affordance discoverable without clicking. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Grab-on-hover felt off in practice. Keep the handle cursor feedback but let the shape hover remain the default arrow, consistent with Figma/Illustrator where the hover highlight is the affordance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a `highlights` Two.js Group as a child of the ZUI-wrapped canvas so selection handles, outlines, marquee, text preview, and bezier node handles live in their own scene-graph subtree. `addDoodle` re-appends the highlights group after each new shape so it stays on top (Two.js `.add` moves an existing child to the end). Drop the `isHighlight` marker and the `if (shape.isHighlight) continue` filters in hit-test and export paths — those iterate the doodles Zustand list, which never contained highlights, so the filters were defensive dead code. Zoom-reactive rescaling (`updateOutlineScales`, `updateNodeHandleScales`) is unchanged: the rebuild helpers now target `doodler.highlights`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the Transform section (rotation/scale/skew sliders) — the canvas handles cover rotation and resize directly, so the sliders were redundant. The Layers panel had its title rendered twice in mismatched styles: once by the outer <Section title="Layers"> wrapper and once by the component's own header (which carries the count). Remove the wrapper and apply Section's text-sm/text-text-secondary styling to the internal header so the count badge is preserved and the styling lines up with other sections. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Give Button and ToggleButton `flex items-center justify-center` so their content aligns with the ButtonGroup container's 26px min-height — the default `align-items: stretch` wasn't enough because <button> line-height left a 2px gap at the bottom. Rename ToggleGroup → ButtonGroup: the bordered container works for both action buttons (undo/redo, zoom) and toggle buttons; toggle-ness lives on the child, not the group. Update call sites and wrap the panel footer's undo/redo and zoom groups in ButtonGroup instead of inlining the bordered flex div. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
doRotatewas rebuilding handles viashowResizeHandles(shapes)every frame, producing a growing/shrinking axis-aligned AABB while the shape rotated — the highlight box visibly lagged behind the shape.startRotateand rotate them around the selection center on each frame, so the selection rectangle tracks the shape tightly (Figma/Illustrator behavior).showResizeHandles(shapes)call inendRotateso handles snap to AABB corners on release —startResizeanchors to AABB corners, so leaving them rotated would break the next corner resize.Test plan
🤖 Generated with Claude Code