Editor's Path Properties section has no 'convert all nodes' button — user with 30 corner nodes wanting to make them all smooth has to select each one and convert (or no bulk operation) #339

Closed
opened 2026-10-04 03:54:28 +00:00 by Mark · 3 comments
Owner

Finding

The EditorContextMenu (per #191) has a "Convert Node Type" submenu for the selected node(s). It's per-selection.

grep -rn 'convertAllNodes\|bulkConvert' src/components/editor/ returns 0. No bulk convert.

A user with 30 corner nodes:

  • Wants to make them all smooth
  • Has to Cmd+A (select all nodes), then "Convert → Smooth"
  • This is one action (per the multi-select) — wait, that may already work

Actually, the multi-select (per #188) selects multiple paths but not all nodes across all paths. To select all nodes:

  • Tab to cycle (one at a time)
  • Or Cmd+A (select all — but this might select paths, not nodes)

The fix is unclear without checking the source. Let me look.

grep -n 'handleSelectAll' src/pages/Editor.tsx — the handler.

Actually, the simpler fix is a "Convert all nodes to smooth/corner/symmetric" button. Per-path bulk is the obvious gap.

Where

  • EditorContextMenu: src/components/editor/EditorContextMenu.tsx (per-node convert)
  • No bulk: grep -rn 'convertAllNodes' src/components/editor/ returns 0
  • The multi-select infrastructure: per #188

Suggested fix shape

  1. UI: in the right panel's Path Properties section, when a path is selected, a small "Convert all nodes" submenu:
<DropdownMenu>
  <DropdownMenuTrigger>
    <ChevronDown size={12} />
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem onClick={() => onConvertAllNodes('corner')}>All → Corner</DropdownMenuItem>
    <DropdownMenuItem onClick={() => onConvertAllNodes('smooth')}>All → Smooth</DropdownMenuItem>
    <DropdownMenuItem onClick={() => onConvertAllNodes('symmetric')}>All → Symmetric</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>
  1. Use cases:
  • A user with a path that should be smooth but has some corners (e.g., from imprecise drawing)
  • A user wanting to add character to a path with all-corner nodes
  • A user with imported paths that are all-corner (common for SVG imports)
  1. History: single undoable action.

Severity

Low. The user can convert one at a time. Power users notice.

Discovered by

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

  • The Convert Node Type (per #191) is the per-node version. This is the per-path-bulk version.
  • #188 (open) — Multi-select. The selection infrastructure.
  • Figma/Illustrator have "Set all corners to smooth." Standard.
## Finding The EditorContextMenu (per #191) has a "Convert Node Type" submenu for the selected node(s). It's per-selection. `grep -rn 'convertAllNodes\|bulkConvert' src/components/editor/` returns 0. No bulk convert. A user with 30 corner nodes: - Wants to make them all smooth - Has to Cmd+A (select all nodes), then "Convert → Smooth" - This is one action (per the multi-select) — wait, that may already work Actually, the multi-select (per #188) selects multiple paths but not all nodes across all paths. To select all nodes: - Tab to cycle (one at a time) - Or Cmd+A (select all — but this might select paths, not nodes) The fix is unclear without checking the source. Let me look. `grep -n 'handleSelectAll' src/pages/Editor.tsx` — the handler. Actually, the simpler fix is a "Convert all nodes to smooth/corner/symmetric" button. Per-path bulk is the obvious gap. ## Where - EditorContextMenu: `src/components/editor/EditorContextMenu.tsx` (per-node convert) - No bulk: `grep -rn 'convertAllNodes' src/components/editor/` returns 0 - The multi-select infrastructure: per #188 ## Suggested fix shape 1. **UI**: in the right panel's Path Properties section, when a path is selected, a small "Convert all nodes" submenu: ```tsx <DropdownMenu> <DropdownMenuTrigger> <ChevronDown size={12} /> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuItem onClick={() => onConvertAllNodes('corner')}>All → Corner</DropdownMenuItem> <DropdownMenuItem onClick={() => onConvertAllNodes('smooth')}>All → Smooth</DropdownMenuItem> <DropdownMenuItem onClick={() => onConvertAllNodes('symmetric')}>All → Symmetric</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> ``` 2. **Use cases**: - A user with a path that should be smooth but has some corners (e.g., from imprecise drawing) - A user wanting to add character to a path with all-corner nodes - A user with imported paths that are all-corner (common for SVG imports) 3. **History**: single undoable action. ## Severity Low. The user can convert one at a time. Power users notice. ## Discovered by Gap analysis (2026-10-02) of editor path operations. ## Related - The Convert Node Type (per #191) is the per-node version. This is the per-path-bulk version. - #188 (open) — Multi-select. The selection infrastructure. - Figma/Illustrator have "Set all corners to smooth." Standard.
Author
Owner

Reopened 2026-10-05 by triage-runner.

The previous kilo-gsd.py run (dispatched 2026-10-04 21:54, completed 2026-10-05 01:55) closed this issue falsely — the fix did not land. Evidence:

  • Working tree on main has zero references to onConvertAllNodes / convertAll / "Convert all nodes" in EditorRightPanel.tsx or Editor.tsx
  • The only commit referencing #339 is dd36a06 which created a placeholder test file (issue-339.test.tsx) containing a colorDistance test — NOT the actual #339 implementation
  • kilo-gsd.py logged "No changes to push" + "Pushed to origin/main" (empty push) before closing the issue
  • Verify gate in the bugfix re-run was using plan per-path-svg-export.md (sibling #346 plan) instead of the actual #339 plan (bulk-convert-all-nodes-plan.md) — verify was approving the wrong artifact.

Re-spawning kilo-gsd.py with explicit instructions to:

  1. Verify that EditorRightPanel.tsx has the convert-all-nodes row BEFORE claiming success (grep for the new feature, do not rely on test pass alone)
  2. Run the actual #339 plan verify commands, not sibling plans
  3. Push a real commit referencing #339 (not just an empty push)

Spec carried from issue body:

  1. Add onConvertAllNodes?: (type) => void to EditorRightPanelProps + destructure
  2. New row in Path Properties section, right under per-node Node Type segmented control, with three buttons: All → Corner, All → Smooth, All → Symmetric
  3. Hide row when onConvertAllNodes omitted (backward compat)
  4. Editor adds handleConvertAllNodes(type): walks every node in every selected path, applies type with same control-handle init as handleUpdateNodeType (smooth/symmetric get +/-10 control handles, corner clears them). One setPaths + one pushHistory + success toast with affected node count.
  5. Wire onConvertAllNodes={handleConvertAllNodes} in Editor
  6. Test: src/components/editor/issue-339.test.tsx pinning render-when-wired, hide-when-omitted, click fires handler with the type
Reopened 2026-10-05 by triage-runner. The previous kilo-gsd.py run (dispatched 2026-10-04 21:54, completed 2026-10-05 01:55) closed this issue falsely — the fix did not land. Evidence: - Working tree on main has zero references to onConvertAllNodes / convertAll / "Convert all nodes" in EditorRightPanel.tsx or Editor.tsx - The only commit referencing #339 is dd36a06 which created a placeholder test file (issue-339.test.tsx) containing a colorDistance test — NOT the actual #339 implementation - kilo-gsd.py logged "No changes to push" + "Pushed to origin/main" (empty push) before closing the issue - Verify gate in the bugfix re-run was using plan `per-path-svg-export.md` (sibling #346 plan) instead of the actual #339 plan (`bulk-convert-all-nodes-plan.md`) — verify was approving the wrong artifact. Re-spawning kilo-gsd.py with explicit instructions to: 1. Verify that EditorRightPanel.tsx has the convert-all-nodes row BEFORE claiming success (grep for the new feature, do not rely on test pass alone) 2. Run the actual #339 plan verify commands, not sibling plans 3. Push a real commit referencing #339 (not just an empty push) Spec carried from issue body: 1. Add onConvertAllNodes?: (type) => void to EditorRightPanelProps + destructure 2. New row in Path Properties section, right under per-node Node Type segmented control, with three buttons: All → Corner, All → Smooth, All → Symmetric 3. Hide row when onConvertAllNodes omitted (backward compat) 4. Editor adds handleConvertAllNodes(type): walks every node in every selected path, applies type with same control-handle init as handleUpdateNodeType (smooth/symmetric get +/-10 control handles, corner clears them). One setPaths + one pushHistory + success toast with affected node count. 5. Wire onConvertAllNodes={handleConvertAllNodes} in Editor 6. Test: src/components/editor/issue-339.test.tsx pinning render-when-wired, hide-when-omitted, click fires handler with the type
Mark 2026-10-05 10:05:55 +00:00
Author
Owner

Reopened 2026-10-05 03:52 PT. Third false close by kilo-gsd.py:

  • 2026-10-05 10:32:50Z: kilo-gsd.py closed #339 after Implement phase ran 32 seconds with zero code changes, then Verify phase ran 4 vacuous commands (placeholder colorDistance test passed, existing EditorRightPanel tests passed, lint passed, tsc passed) — gate vacuously passed.
  • The implementer used reasoning=nvidia/moonshotai/kimi-k3 + coding=nvidia/mistralai/mistral-large-2-instruct (from kilo.env) and exited cleanly with no work, treating the existing placeholder issue-339.test.tsx as evidence the feature was already implemented. The placeholder is just a colorDistance smoke test, NOT the feature test.
  • This is a recurrence of the 2026-10-04 21:54 false close (#339 closed with no commit) and the 2026-10-05 02:02 reclose (#339 had been reopened by triage-runner; the false close happened again on the second attempt).
  • After three false closes, triage-runner is taking the inline-fix path: editing EditorRightPanel.tsx + Editor.tsx + replacing the placeholder test directly. Plan file at .kilo/plans/1791191069368-issue-339-convert-all-nodes.md has the full spec.
Reopened 2026-10-05 03:52 PT. Third false close by kilo-gsd.py: - 2026-10-05 10:32:50Z: kilo-gsd.py closed #339 after Implement phase ran 32 seconds with zero code changes, then Verify phase ran 4 vacuous commands (placeholder colorDistance test passed, existing EditorRightPanel tests passed, lint passed, tsc passed) — gate vacuously passed. - The implementer used reasoning=nvidia/moonshotai/kimi-k3 + coding=nvidia/mistralai/mistral-large-2-instruct (from kilo.env) and exited cleanly with no work, treating the existing placeholder issue-339.test.tsx as evidence the feature was already implemented. The placeholder is just a `colorDistance` smoke test, NOT the feature test. - This is a recurrence of the 2026-10-04 21:54 false close (#339 closed with no commit) and the 2026-10-05 02:02 reclose (#339 had been reopened by triage-runner; the false close happened again on the second attempt). - After three false closes, triage-runner is taking the inline-fix path: editing EditorRightPanel.tsx + Editor.tsx + replacing the placeholder test directly. Plan file at .kilo/plans/1791191069368-issue-339-convert-all-nodes.md has the full spec.
Author
Owner

Implemented and pushed in commit f77f9c2 (origin/main). The bulk "Convert all nodes" tri-button (corner / smooth / symmetric) is now in the Editor right panel — retypes every node of every selected path in a single setPaths + pushHistory (one Ctrl+Z step). Multi-select fan-out via selectedPathIds (#188). Backwards-compatible: the section only renders when onConvertAllNodesOfSelectedPath is wired. 5-test feature suite at src/components/editor/issue-339.test.tsx (replaces the placeholder). All 216 tests pass (211 EditorRightPanel + 5 #339).

Implemented and pushed in commit f77f9c2 (origin/main). The bulk "Convert all nodes" tri-button (corner / smooth / symmetric) is now in the Editor right panel — retypes every node of every selected path in a single setPaths + pushHistory (one Ctrl+Z step). Multi-select fan-out via selectedPathIds (#188). Backwards-compatible: the section only renders when onConvertAllNodesOfSelectedPath is wired. 5-test feature suite at src/components/editor/issue-339.test.tsx (replaces the placeholder). All 216 tests pass (211 EditorRightPanel + 5 #339).
Sign in to join this conversation.
No description provided.