Editor's Node Properties has no 'break handles' or 'link handles' toggle — user with a smooth node wanting to make the two handles independent (smooth) or mirrored (symmetric) has no UI to toggle this #361

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

Finding

grep -rn 'breakHandles\|linkHandles\|handleLinked' src/components/editor/ returns 0. The editor has no break/link handles toggle.

A user with a smooth node:

  • The two handles are linked (when one moves, the other mirrors)
  • Wants to "break" the link, edit one handle independently
  • Currently: no way; the node type is fixed at creation

Wait, smooth vs symmetric in the editor:

  • Smooth: handles are tangent (collinear) but can have different lengths
  • Symmetric: handles are tangent AND have the same length

So smooth already allows independent handle lengths. Symmetric enforces equal.

The "break handles" / "link handles" is a different concept:

  • Linked: when one handle moves, the other mirrors (like symmetric)
  • Broken: when one handle moves, the other doesn't (like smooth)

The current smooth/symmetric dichotomy is binary. Real Bezier editors have a "broken" mode (independent) and a "linked" mode (mirrored).

The fix is to add a third node type: "broken smooth" (smooth but handles can be different lengths, no mirror).

Where

  • Node Properties: src/components/editor/EditorRightPanel.tsx
  • The Convert Node Type (per #191): 3 options (corner, smooth, symmetric)
  • No broken: grep -rn 'broken' src/components/editor/ returns 0

Suggested fix shape

  1. Type: the node type can be 'corner' | 'smooth' | 'symmetric' | 'broken' (or 'independent').

  2. UI: in the Convert Node Type submenu, add "Broken smooth" as a 4th option.

  3. Use cases:

  • The user wants smooth but with custom handle lengths (no auto-mirror)
  • The user is editing imported paths and wants to fix the handle constraints
  1. Bezier handles (per #251): when the user has Bezier handles, this becomes more important — they can drag each handle independently.

Severity

Low. The user can choose smooth or symmetric. Power users notice.

Discovered by

Gap analysis (2026-10-02) of editor node type UI.

  • #251 (open) — Bezier handles. The handles are the underlying data.
  • #359 (open) — Convert Node Type clearer labels. Same surface.
  • Figma has "Independent" as a node type. The editor's gap is the parallel.
## Finding `grep -rn 'breakHandles\|linkHandles\|handleLinked' src/components/editor/` returns 0. The editor has no break/link handles toggle. A user with a smooth node: - The two handles are linked (when one moves, the other mirrors) - Wants to "break" the link, edit one handle independently - Currently: no way; the node type is fixed at creation Wait, smooth vs symmetric in the editor: - Smooth: handles are tangent (collinear) but can have different lengths - Symmetric: handles are tangent AND have the same length So smooth already allows independent handle lengths. Symmetric enforces equal. The "break handles" / "link handles" is a different concept: - Linked: when one handle moves, the other mirrors (like symmetric) - Broken: when one handle moves, the other doesn't (like smooth) The current smooth/symmetric dichotomy is binary. Real Bezier editors have a "broken" mode (independent) and a "linked" mode (mirrored). The fix is to add a third node type: "broken smooth" (smooth but handles can be different lengths, no mirror). ## Where - Node Properties: `src/components/editor/EditorRightPanel.tsx` - The Convert Node Type (per #191): 3 options (corner, smooth, symmetric) - No broken: `grep -rn 'broken' src/components/editor/` returns 0 ## Suggested fix shape 1. **Type**: the node type can be 'corner' | 'smooth' | 'symmetric' | 'broken' (or 'independent'). 2. **UI**: in the Convert Node Type submenu, add "Broken smooth" as a 4th option. 3. **Use cases**: - The user wants smooth but with custom handle lengths (no auto-mirror) - The user is editing imported paths and wants to fix the handle constraints 4. **Bezier handles** (per #251): when the user has Bezier handles, this becomes more important — they can drag each handle independently. ## Severity Low. The user can choose smooth or symmetric. Power users notice. ## Discovered by Gap analysis (2026-10-02) of editor node type UI. ## Related - #251 (open) — Bezier handles. The handles are the underlying data. - #359 (open) — Convert Node Type clearer labels. Same surface. - Figma has "Independent" as a node type. The editor's gap is the parallel.
Author
Owner

Closing as a stale gap-analysis finding — the behaviour this issue asks for already exists as the smooth node type.

The body of #361 conflates two different concepts. After re-reading:

  • The issue says smooth = "linked" (handles mirror when one moves).
  • The actual behaviour of smooth is "broken": handles do not mirror — moving one does not move the other. The canvas drag handler in src/pages/Editor.tsx (handleUpdateControlPoint, ~lines 1977-2041) only writes the opposite handle when target.type === 'symmetric'; for smooth it touches only the requested handle.

Cited evidence:

  1. Canvas drag behaviour (src/pages/Editor.tsx:2017-2034): the symmetric-mirror branch is gated on target.type === 'symmetric'. The smooth branch only sets [field], leaving [otherField] alone. Comment at line 1984: "Smooth nodes only touch the requested handle."

  2. Numeric-input behaviour (same handler): "For symmetric nodes we mirror the change onto the opposite handle so the bezier stays anti-symmetric around the anchor — same rule the canvas drag already obeys". Smooth: just return { ...n, [field]: ... }.

  3. In-UI tooltip text added in #359 (commit 07db222):

    • Smooth: "the two handles are collinear (the curve is tangent at this node), but the handle lengths can differ"
    • Symmetric: "tangent at this node AND the two handles are the same length (180° / equal magnitude)"
  4. Definition (src/components/editor/types.ts:3): export type NodeType = 'corner' | 'smooth' | 'symmetric' — three options, with smooth already being the "broken, handles can differ" case the issue asks for.

The body's suggested fix ("add a fourth type: 'broken' or 'independent'") would be a synonym for smooth — same semantics, different label. That would add a 4th button to the tri-button widget that maps to behaviour already covered by Smooth, making the UI more confusing rather than less. The intent of the issue (the user wanted to move one handle without dragging the other) is already what smooth does — no breakHandles/linkHandles toggle is needed; switching to smooth is the answer.

If the original report was driven by a specific path where moving one handle seemed to move the other, the most likely explanation is the node was symmetric and the user wanted smooth — the existing Node Type tri-button (corner / smooth / symmetric) in the right panel is exactly that toggle. If there's a concrete reproduction where a smooth node's handles are mirroring, that would be a real bug and worth a new issue with the path + steps.

Closing as a stale gap-analysis finding — the behaviour this issue asks for already exists as the `smooth` node type. The body of #361 conflates two different concepts. After re-reading: - The issue says `smooth` = "linked" (handles mirror when one moves). - The actual behaviour of `smooth` is "broken": handles do **not** mirror — moving one does not move the other. The canvas drag handler in `src/pages/Editor.tsx` (handleUpdateControlPoint, ~lines 1977-2041) only writes the opposite handle when `target.type === 'symmetric'`; for `smooth` it touches only the requested handle. Cited evidence: 1. **Canvas drag behaviour** (`src/pages/Editor.tsx:2017-2034`): the symmetric-mirror branch is gated on `target.type === 'symmetric'`. The smooth branch only sets `[field]`, leaving `[otherField]` alone. Comment at line 1984: "Smooth nodes only touch the requested handle." 2. **Numeric-input behaviour** (same handler): "For symmetric nodes we mirror the change onto the opposite handle so the bezier stays anti-symmetric around the anchor — same rule the canvas drag already obeys". Smooth: just `return { ...n, [field]: ... }`. 3. **In-UI tooltip text** added in #359 (commit 07db222): - Smooth: *"the two handles are collinear (the curve is tangent at this node), but the handle lengths can differ"* - Symmetric: *"tangent at this node AND the two handles are the same length (180° / equal magnitude)"* 4. **Definition** (`src/components/editor/types.ts:3`): `export type NodeType = 'corner' | 'smooth' | 'symmetric'` — three options, with `smooth` already being the "broken, handles can differ" case the issue asks for. The body's suggested fix ("add a fourth type: 'broken' or 'independent'") would be a synonym for `smooth` — same semantics, different label. That would add a 4th button to the tri-button widget that maps to behaviour already covered by Smooth, making the UI more confusing rather than less. The intent of the issue (the user wanted to move one handle without dragging the other) is already what `smooth` does — no `breakHandles`/`linkHandles` toggle is needed; switching to smooth is the answer. If the original report was driven by a specific path where moving one handle seemed to move the other, the most likely explanation is the node was `symmetric` and the user wanted `smooth` — the existing Node Type tri-button (corner / smooth / symmetric) in the right panel is exactly that toggle. If there's a concrete reproduction where a `smooth` node's handles are mirroring, that would be a real bug and worth a new issue with the path + steps.
Mark closed this issue 2026-10-05 13:49:01 +00:00
Sign in to join this conversation.
No description provided.