Editor has no 'bring to front' / 'send to back' / 'z-order' operations for paths — user with overlapping paths (e.g., a circle behind a star) can't reorder which is drawn on top, only the array order (draw order) is in effect #290

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

Finding

grep -rn 'bringToFront\|sendToBack' src/components/editor/ returns 0 hits. The editor has no z-order operations.

The workspace's ContextMenu (per the snippet I saw earlier) DOES have Bring to Front / Send to Back. The editor's EditorContextMenu (per #191) does NOT.

A user with 3 overlapping paths:

  • A red circle in the back
  • A blue square in the middle
  • A green star in the front

If the array order is wrong (green before blue), the green star is hidden by the blue square. The user wants to bring the green to the front.

Currently:

  • No way to reorder the array
  • Has to delete the green, recreate it (it goes to the end of the array, which is "in front")
  • 3 steps

Where

  • EditorContextMenu: src/components/editor/EditorContextMenu.tsx (no z-order items)
  • Workspace's ContextMenu: src/components/workspace/ContextMenu.tsx (HAS Bring to Front, Send to Back)
  • No editor z-order: grep -rn 'bringToFront' src/components/editor/ returns 0

Suggested fix shape

  1. State: the path array order is the z-order. The first path is in the back, the last is in the front.

  2. UI: add to the EditorContextMenu (per #191):

{/* In the empty-space / node / segment menu */}
<ContextMenuItem onClick={() => onBringToFront(selectedPathId)}>
  <ChevronsUp size={12} /> Bring to Front
</ContextMenuItem>
<ContextMenuItem onClick={() => onSendToBack(selectedPathId)}>
  <ChevronsDown size={12} /> Send to Back
</ContextMenuItem>
<ContextMenuItem onClick={() => onMoveForward(selectedPathId)}>
  <ChevronUp size={12} /> Move Forward
</ContextMenuItem>
<ContextMenuItem onClick={() => onMoveBackward(selectedPathId)}>
  <ChevronDown size={12} /> Move Backward
</ContextMenuItem>
  1. Implementation:
const onBringToFront = (pathId: string) => {
  setPaths((prev) => {
    const idx = prev.findIndex((p) => p.id === pathId);
    if (idx === -1 || idx === prev.length - 1) return prev;
    const next = [...prev];
    const [moved] = next.splice(idx, 1);
    next.push(moved);
    return next;
  });
};

The Send to Back, Move Forward, Move Backward follow the same pattern.

  1. History: each reorder is a single undoable action.

Severity

Low. The user can delete + recreate. Power users with overlapping shapes notice.

Discovered by

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

  • The workspace's ContextMenu has these items; the editor's is the parallel.
  • #259 (open) — Group. Group operations often include z-order; the editor's z-order is the standalone version.
  • Figma/Illustrator have Right-click → Arrange → Bring to Front / Send to Back. Standard.
## Finding `grep -rn 'bringToFront\|sendToBack' src/components/editor/` returns 0 hits. The editor has no z-order operations. The workspace's `ContextMenu` (per the snippet I saw earlier) DOES have Bring to Front / Send to Back. The editor's `EditorContextMenu` (per #191) does NOT. A user with 3 overlapping paths: - A red circle in the back - A blue square in the middle - A green star in the front If the array order is wrong (green before blue), the green star is hidden by the blue square. The user wants to bring the green to the front. Currently: - No way to reorder the array - Has to delete the green, recreate it (it goes to the end of the array, which is "in front") - 3 steps ## Where - EditorContextMenu: `src/components/editor/EditorContextMenu.tsx` (no z-order items) - Workspace's ContextMenu: `src/components/workspace/ContextMenu.tsx` (HAS Bring to Front, Send to Back) - No editor z-order: `grep -rn 'bringToFront' src/components/editor/` returns 0 ## Suggested fix shape 1. **State**: the path array order is the z-order. The first path is in the back, the last is in the front. 2. **UI**: add to the EditorContextMenu (per #191): ```tsx {/* In the empty-space / node / segment menu */} <ContextMenuItem onClick={() => onBringToFront(selectedPathId)}> <ChevronsUp size={12} /> Bring to Front </ContextMenuItem> <ContextMenuItem onClick={() => onSendToBack(selectedPathId)}> <ChevronsDown size={12} /> Send to Back </ContextMenuItem> <ContextMenuItem onClick={() => onMoveForward(selectedPathId)}> <ChevronUp size={12} /> Move Forward </ContextMenuItem> <ContextMenuItem onClick={() => onMoveBackward(selectedPathId)}> <ChevronDown size={12} /> Move Backward </ContextMenuItem> ``` 3. **Implementation**: ```ts const onBringToFront = (pathId: string) => { setPaths((prev) => { const idx = prev.findIndex((p) => p.id === pathId); if (idx === -1 || idx === prev.length - 1) return prev; const next = [...prev]; const [moved] = next.splice(idx, 1); next.push(moved); return next; }); }; ``` The Send to Back, Move Forward, Move Backward follow the same pattern. 4. **History**: each reorder is a single undoable action. ## Severity Low. The user can delete + recreate. Power users with overlapping shapes notice. ## Discovered by Gap analysis (2026-10-02) of editor path operations. ## Related - The workspace's `ContextMenu` has these items; the editor's is the parallel. - #259 (open) — Group. Group operations often include z-order; the editor's z-order is the standalone version. - Figma/Illustrator have Right-click → Arrange → Bring to Front / Send to Back. Standard.
Author
Owner

Closed by fix(#290) at e6eb946 on origin/main. Adds four z-order operations (Bring to Front, Send to Back, Move Forward, Move Backward) to the editor context menu. Single history entry per reorder, dirty flag, no-op guard when the path is already at the requested extreme. Each item disabled in the UI with an explanatory tooltip when the operation would be a no-op.

Closed by fix(#290) at e6eb946 on origin/main. Adds four z-order operations (Bring to Front, Send to Back, Move Forward, Move Backward) to the editor context menu. Single history entry per reorder, dirty flag, no-op guard when the path is already at the requested extreme. Each item disabled in the UI with an explanatory tooltip when the operation would be a no-op.
Mark closed this issue 2026-10-04 18:26:48 +00:00
Sign in to join this conversation.
No description provided.