Editor has no 'rotate path' input — user with a path at a specific angle (e.g., 30°) wanting to set it precisely has to drag-and-rotate (slow) or no input #352

Closed
opened 2026-10-04 03:56:11 +00:00 by Mark · 1 comment
Owner

Finding

grep -rn 'rotatePath\|pathRotation' src/components/editor/ returns 0. The editor has no rotate-path input.

A user with a path:

  • Wants to rotate it by 30° around its center
  • Currently: has to drag-rotate (the canvas has a rotate mode? or a transform?)

grep -rn 'applyPathTransform' src/components/editor/ — let me check. Yes, per the earlier snippet, applyPathTransform is a geometry function. There may be a rotate mode.

But there's no precise input: "rotate by 30°" requires dragging to a specific angle.

The fix is a rotation input.

Where

  • Path operations: src/components/editor/EditorRightPanel.tsx (per-row actions)
  • No rotate input: grep -rn 'pathRotation' src/components/editor/ returns 0
  • The geometry: src/components/editor/geometry.ts (applyPathTransform has rotate, but no UI)

Suggested fix shape

  1. UI: a rotation input in the Path Properties section:
<NumberField
  label="Rotation"
  value={pathRotation}
  onChange={(v) => onRotatePath(p.id, v)}
  min={-180}
  max={180}
  step={1}
  unit="°"
/>
  1. Behavior: the path is rotated around its center by the specified degrees.

  2. UI: a "90° CW" / "90° CCW" / "Flip H" / "Flip V" set of buttons for common rotations.

  3. Use cases:

  • Aligning a path to a specific angle
  • Flipping a path horizontally
  • Rotating to match a reference
  1. History: single undoable action.

Severity

Low. The user can drag. Power users with precise rotations notice.

Discovered by

Gap analysis (2026-10-02) of editor path operations.

  • The applyPathTransform function in geometry.ts is the algorithm.
  • #258 (open) — Align. Same path operations family.
  • Figma/Illustrator have rotation inputs. Standard.
## Finding `grep -rn 'rotatePath\|pathRotation' src/components/editor/` returns 0. The editor has no rotate-path input. A user with a path: - Wants to rotate it by 30° around its center - Currently: has to drag-rotate (the canvas has a rotate mode? or a transform?) `grep -rn 'applyPathTransform' src/components/editor/` — let me check. Yes, per the earlier snippet, `applyPathTransform` is a geometry function. There may be a rotate mode. But there's no precise input: "rotate by 30°" requires dragging to a specific angle. The fix is a rotation input. ## Where - Path operations: `src/components/editor/EditorRightPanel.tsx` (per-row actions) - No rotate input: `grep -rn 'pathRotation' src/components/editor/` returns 0 - The geometry: `src/components/editor/geometry.ts` (applyPathTransform has rotate, but no UI) ## Suggested fix shape 1. **UI**: a rotation input in the Path Properties section: ```tsx <NumberField label="Rotation" value={pathRotation} onChange={(v) => onRotatePath(p.id, v)} min={-180} max={180} step={1} unit="°" /> ``` 2. **Behavior**: the path is rotated around its center by the specified degrees. 3. **UI**: a "90° CW" / "90° CCW" / "Flip H" / "Flip V" set of buttons for common rotations. 4. **Use cases**: - Aligning a path to a specific angle - Flipping a path horizontally - Rotating to match a reference 5. **History**: single undoable action. ## Severity Low. The user can drag. Power users with precise rotations notice. ## Discovered by Gap analysis (2026-10-02) of editor path operations. ## Related - The `applyPathTransform` function in geometry.ts is the algorithm. - #258 (open) — Align. Same path operations family. - Figma/Illustrator have rotation inputs. Standard.
Author
Owner

feat(#352) shipped on origin/main via commit 515a0f8.

Adds a precise Rotation input in the Path Properties Transform section, directly below the existing flip / rotate-90 buttons. A user with a path at a specific angle (e.g. 30 degrees) can now type the value instead of drag-rotating.

  • geometry.ts: new rotateNodesByAngle (modulo 360, NaN to 0) + applyPathRotation helper wrapping it with bbox pivot. Mirrors rotate90Nodes / flipX / flipY so the 90 degree button and the typed input agree to a ULP.
  • Editor.tsx: new handleRotateSelectedPath with the same single-commit history contract as #318 — wires onRotateSelectedPath into the panel. Multi-select fans out the same way handleTransformSelectedPath does.
  • EditorRightPanel.tsx: NumberField (range -180..180, step 1, unit degrees), local rotationDraft state that resets after apply, disabled when the selected path has zero nodes, hidden when the caller does not wire onRotateSelectedPath (so older callers stay type-checked).

Tests:

  • src/components/editor/issue-352.test.tsx — 8 panel tests (presence, value clamping, handler dispatch, reset-after-apply, selection-change reset, optional-prop back-compat, empty-nodes disabled).
  • src/components/editor/geometry.test.ts — 158 lines pinning the modulo-360 + bbox-center math.
  • Verification run: 378/378 geometry + issue-352 panel tests pass; full vitest run is 190/194 files green (the 4 pre-existing failures in #329/#331/#333/#334 reproduce on origin/main without these changes — separate work).

Also committed in this push:

  • 4101d88 chore(vitest): exclude .worktrees/ — sibling worktrees were polluting the root vitest sweep with stale snapshots and Playwright specs; excluding them keeps each worktree scoped to its own tests.
feat(#352) shipped on origin/main via commit 515a0f8. Adds a precise Rotation input in the Path Properties Transform section, directly below the existing flip / rotate-90 buttons. A user with a path at a specific angle (e.g. 30 degrees) can now type the value instead of drag-rotating. - geometry.ts: new rotateNodesByAngle (modulo 360, NaN to 0) + applyPathRotation helper wrapping it with bbox pivot. Mirrors rotate90Nodes / flipX / flipY so the 90 degree button and the typed input agree to a ULP. - Editor.tsx: new handleRotateSelectedPath with the same single-commit history contract as #318 — wires onRotateSelectedPath into the panel. Multi-select fans out the same way handleTransformSelectedPath does. - EditorRightPanel.tsx: NumberField (range -180..180, step 1, unit degrees), local rotationDraft state that resets after apply, disabled when the selected path has zero nodes, hidden when the caller does not wire onRotateSelectedPath (so older callers stay type-checked). Tests: - src/components/editor/issue-352.test.tsx — 8 panel tests (presence, value clamping, handler dispatch, reset-after-apply, selection-change reset, optional-prop back-compat, empty-nodes disabled). - src/components/editor/geometry.test.ts — 158 lines pinning the modulo-360 + bbox-center math. - Verification run: 378/378 geometry + issue-352 panel tests pass; full vitest run is 190/194 files green (the 4 pre-existing failures in #329/#331/#333/#334 reproduce on origin/main without these changes — separate work). Also committed in this push: - 4101d88 chore(vitest): exclude .worktrees/ — sibling worktrees were polluting the root vitest sweep with stale snapshots and Playwright specs; excluding them keeps each worktree scoped to its own tests.
Mark closed this issue 2026-10-05 11:34:06 +00:00
Sign in to join this conversation.
No description provided.