Workspace's right panel has no per-object delete button — Delete lives only in the right-click context menu, which is undiscoverable and off the primary editing surface #199

Closed
opened 2026-10-03 23:51:17 +00:00 by Mark · 1 comment
Owner

Finding

src/components/workspace/RightPanel.tsx's Object List section (the part that renders one card per colorRegion or stitchObject) has no delete affordance. The user can:

  • Right-click a card on the canvas to open the context menu (which has Delete)
  • Press Del when the canvas is focused

grep -n 'DELETE_SELECTED\|delete.*selected' src/components/workspace/RightPanel.tsx returns 0 hits. The right panel's per-object card has no delete button.

A new user who:

  • Uploads an image
  • Auto-digitizes
  • Sees 4 stitch objects
  • Wants to remove one

...has to:

  1. Right-click the object on the canvas (must select it first)
  2. Pick "Delete" from the context menu
  3. Confirm (no confirm in current impl, but the action is hidden behind two clicks)

Or, the more discoverable path:

  1. Click the object on the canvas (selects it)
  2. Press the Delete key

But there's no visual hint that "Delete" does anything. The context menu hint (per #176) is also broken.

The right panel is the primary surface for browsing objects; it should have a per-object delete.

Where

  • Right panel: src/components/workspace/RightPanel.tsx (Object List section)
  • No delete: grep -n 'DELETE_SELECTED' src/components/workspace/RightPanel.tsx returns 0
  • Context menu has delete: src/components/workspace/ContextMenu.tsx:78-80
  • DELETE_SELECTED action exists: src/components/workspace/useWorkspace.ts:308

Suggested fix shape

Add a small "×" button to the right panel's per-object card (visible on hover):

<button
  onClick={() => dispatch({ type: 'DELETE_SELECTED' })}
  data-testid={`delete-object-${obj.id}`}
  className="opacity-0 group-hover:opacity-100 w-5 h-5 flex items-center justify-center rounded transition-opacity"
  title="Delete this object"
>
  <X size={10} />
</button>

The DELETE_SELECTED action is already in the reducer and deletes the currently selected objects. The right panel's "Object List" card already tracks which object is selected; clicking delete on the card either:

  • Selects that object first, then dispatches DELETE_SELECTED
  • Or has a dedicated DELETE_OBJECT action that takes an id

Option 2 (dedicated action) is more straightforward — the right panel's per-object card can delete without first selecting.

Severity

Medium. The right panel is the primary surface; affordances should be there. Right-click context menus are a power-user pattern, not a discoverability pattern.

Discovered by

Gap analysis (2026-10-02) of workspace object affordances.

  • #176 (open) — Workspace's context menu shows keyboard shortcut hints that don't work. The context menu's discoverability is one half; the right panel's delete button is the other half.
  • #190 (open) — BottomThreadBar's stop pills have no remove affordance. Same shape: primary surface missing a remove button.
## Finding `src/components/workspace/RightPanel.tsx`'s Object List section (the part that renders one card per `colorRegion` or `stitchObject`) has no delete affordance. The user can: - Right-click a card on the canvas to open the context menu (which has Delete) - Press Del when the canvas is focused `grep -n 'DELETE_SELECTED\|delete.*selected' src/components/workspace/RightPanel.tsx` returns 0 hits. The right panel's per-object card has no delete button. A new user who: - Uploads an image - Auto-digitizes - Sees 4 stitch objects - Wants to remove one ...has to: 1. Right-click the object on the canvas (must select it first) 2. Pick "Delete" from the context menu 3. Confirm (no confirm in current impl, but the action is hidden behind two clicks) Or, the more discoverable path: 1. Click the object on the canvas (selects it) 2. Press the Delete key But there's no visual hint that "Delete" does anything. The context menu hint (per #176) is also broken. The right panel is the primary surface for browsing objects; it should have a per-object delete. ## Where - Right panel: `src/components/workspace/RightPanel.tsx` (Object List section) - No delete: `grep -n 'DELETE_SELECTED' src/components/workspace/RightPanel.tsx` returns 0 - Context menu has delete: `src/components/workspace/ContextMenu.tsx:78-80` - DELETE_SELECTED action exists: `src/components/workspace/useWorkspace.ts:308` ## Suggested fix shape Add a small "×" button to the right panel's per-object card (visible on hover): ```tsx <button onClick={() => dispatch({ type: 'DELETE_SELECTED' })} data-testid={`delete-object-${obj.id}`} className="opacity-0 group-hover:opacity-100 w-5 h-5 flex items-center justify-center rounded transition-opacity" title="Delete this object" > <X size={10} /> </button> ``` The `DELETE_SELECTED` action is already in the reducer and deletes the currently selected objects. The right panel's "Object List" card already tracks which object is selected; clicking delete on the card either: - Selects that object first, then dispatches DELETE_SELECTED - Or has a dedicated `DELETE_OBJECT` action that takes an id Option 2 (dedicated action) is more straightforward — the right panel's per-object card can delete without first selecting. ## Severity Medium. The right panel is the primary surface; affordances should be there. Right-click context menus are a power-user pattern, not a discoverability pattern. ## Discovered by Gap analysis (2026-10-02) of workspace object affordances. ## Related - #176 (open) — Workspace's context menu shows keyboard shortcut hints that don't work. The context menu's discoverability is one half; the right panel's delete button is the other half. - #190 (open) — BottomThreadBar's stop pills have no remove affordance. Same shape: primary surface missing a remove button.
Author
Owner

Shipped in commit 9d0966b (fix(#199)).

What landed:

  • New DELETE_OBJECT { id } reducer action in useWorkspace.ts — mirrors DELETE_SELECTED's compound group cascade (#67) so deleting a grouped member removes the whole group, matching the existing right-click / Del-key affordance. Pushes history so undo/redo round-trip the deletion.
  • Per-object delete button (×) on each ObjectList row in RightPanel.tsx:
    • Renders as the last child of each row (after the eye/lock toggles for stitchObjects, after the stitchType pill for colorRegions)
    • Hidden at rest (opacity-0), fades in on row hover via group-hover:opacity-100 — mirrors the visual treatment of the existing per-row toggles
    • Click stopPropagations so the row's onClick (SELECT) doesn't fire alongside the delete
    • aria-label="Delete <name>" for screen-reader discoverability

Tests: src/components/workspace/issue-199.test.tsx — 5 cases (button renders per row in both digitized → stitchObjects and digitizing → colorRegions branches; click dispatches DELETE_OBJECT with the right id; click does NOT also fire SELECT; aria-label names the object).

Verification:

  • vitest: 914 passed / 1 skipped (the new 5 included)
  • eslint: clean
  • tsc -b: clean

Refs #176 (context-menu keyboard hint), #190 (BottomThreadBar stop pill × button — same pattern, third surface now covered).

Closes #199

Shipped in commit [9d0966b](https://forgejo.tail018ac4.ts.net/Mark/Kimi_Agent_Brother_10_Digitizing_App/commit/9d0966bedf3266b9dc62522445622c5e34215e8f) (fix(#199)). **What landed:** - New `DELETE_OBJECT { id }` reducer action in `useWorkspace.ts` — mirrors `DELETE_SELECTED`'s compound group cascade (#67) so deleting a grouped member removes the whole group, matching the existing right-click / Del-key affordance. Pushes history so undo/redo round-trip the deletion. - Per-object delete button (×) on each `ObjectList` row in `RightPanel.tsx`: - Renders as the last child of each row (after the eye/lock toggles for stitchObjects, after the stitchType pill for colorRegions) - Hidden at rest (`opacity-0`), fades in on row hover via `group-hover:opacity-100` — mirrors the visual treatment of the existing per-row toggles - Click `stopPropagation`s so the row's `onClick` (SELECT) doesn't fire alongside the delete - `aria-label="Delete <name>"` for screen-reader discoverability **Tests:** `src/components/workspace/issue-199.test.tsx` — 5 cases (button renders per row in both `digitized` → `stitchObjects` and `digitizing` → `colorRegions` branches; click dispatches `DELETE_OBJECT` with the right id; click does NOT also fire `SELECT`; aria-label names the object). **Verification:** - vitest: 914 passed / 1 skipped (the new 5 included) - eslint: clean - tsc -b: clean Refs #176 (context-menu keyboard hint), #190 (BottomThreadBar stop pill × button — same pattern, third surface now covered). Closes #199
Mark closed this issue 2026-10-04 01:38:50 +00:00
Sign in to join this conversation.
No description provided.