Skip to content

feat(toolpath-desktop): html-card graph viz with expandable dead branches#23

Merged
eliot-emp merged 1 commit intomainfrom
eliot/amazing-shockley-741863
Apr 20, 2026
Merged

feat(toolpath-desktop): html-card graph viz with expandable dead branches#23
eliot-emp merged 1 commit intomainfrom
eliot/amazing-shockley-741863

Conversation

@eliothedeman
Copy link
Copy Markdown
Collaborator

Summary

  • Replaces the dagre-d3-es SVG renderer in the desktop Preview with HTML cards laid out by @dagrejs/dagre plus an SVG edge overlay.
  • Dead-end subtrees are hidden by default behind a stacked-shadow peek; each HEAD card that has dead children gets an expand / collapse chip that re-layouts the graph including (or re-hiding) that branch.
  • Card design uses the existing desktop palette (cream / rust) and shows id + intent + actor + HEAD/dead chips in the graph itself. The right-side detail panel still carries the full diff for the selected step.

Why

Long Claude sessions produced unreadable, edge-heavy SVG graphs where dead branches dominated the canvas. The new layout:

  • Uses plain HTML for node content so we get CSS reuse (palette, typography, hover/focus states) and richer per-step info in the graph itself.
  • Progressively discloses dead branches, so a 1700-step path is still navigable — you only pay layout cost for the branches you explicitly open.
  • Keeps the detail panel unchanged, so expensive diff rendering stays out of the graph.

What changed

Frontend deps (crates/toolpath-desktop/frontend/package.json)

  • Added @dagrejs/dagre; dropped d3, @types/d3, dagre-d3-es (no longer used).

Model (types.ts + update.ts)

  • `PreviewSlice.showDead: boolean` -> `expandedBranches: Record<string, true>`.
  • Dropped `showDead` from the `PreviewToggle` msg key union.
  • New `PreviewToggleBranch { nodeId }` msg + handler (toggles membership in `expandedBranches`, bumps `vizEpoch`).
  • `DeriveSucceeded` initializes `expandedBranches: {}`.

Renderer (lib/viz.ts)

  • Complete rewrite. Uses `@dagrejs/dagre` for layout and renders HTML cards positioned absolutely + SVG edge paths with arrow markers.
  • Cards show id, intent (clamped to 3 lines), actor, chips (HEAD / dead), and an expand/collapse chip when the card has dead children.
  • Dead branches hidden by default; HEAD cards with hidden children get a stacked-shadow peek via multi-layer `box-shadow`.
  • Edges: muted grey for HEAD-path; `--danger` red + dashed for dead-child edges.

Preview component (Preview.svelte)

  • Swapped `` for a `
    ` bound to the graph container.
  • Dropped the Dead Ends checkbox (replaced by per-branch expand). Kept Timestamps / Files touched.

Layout (app.svelte + styles.css)

  • Preview route now gets a `screen--wide` modifier that removes the 560px `max-width` cap so the graph has room.
  • Added `.path-graph*` and `.pg-card*` rules using the desktop palette; `.preview-canvas` switched to `overflow: auto` so wide/tall graphs scroll.

Design prototype (index.html at repo root)

  • Self-contained single-file prototype the UX was iterated against. Easy to delete if we don't want it checked in — leaving it for reviewer discretion.

Test plan

  • `bun run check` — 0 errors (9 pre-existing a11y warnings in untouched routes).
  • `bun run build` — clean build, ~123 KB JS gzipped.
  • `cargo tauri dev`: derive a Claude session, open Preview; verify HEAD path renders as a vertical chain, dead-branch HEAD cards show the stacked-shadow peek, and the expand chip reveals the dead subtree with red dashed edges.
  • Click a card -> right panel shows full step metadata + diff. Focused card gets the accent ring.
  • Derive a deeply nested session (~1000+ steps) and confirm scrolling/perf is acceptable; if not, follow up with virtualization/zoom-to-fit.

…ches

Replaces the dagre-d3-es SVG renderer in the Preview with HTML cards laid
out by @dagrejs/dagre + an SVG edge overlay. The default view shows only
the HEAD-path; each HEAD card that has dead children renders with a
stacked-shadow peek and a small "expand" chip — clicking the chip flips
a key in preview.expandedBranches and the graph re-layouts to include
the dead subtree.

Why: the SVG-node viz didn't scale readably to longer Claude sessions,
and dead-end branches dominated the canvas for no user benefit. Cards
as HTML let us reuse the desktop palette (cream/rust) and show richer
per-step metadata (id, intent, actor, optional timestamps + files) in
the graph itself while keeping the existing detail panel for full diffs.

- Add @dagrejs/dagre; drop d3/@types/d3/dagre-d3-es (now unused).
- Model: replace PreviewSlice.showDead with expandedBranches: Record<string, true>;
  add PreviewToggleBranch { nodeId } msg + handler; bump vizEpoch on toggle.
- Rewrite lib/viz.ts as renderCard + dagre-layout + SVG edge paths.
  Dead edges render red + dashed; arrowheads via SVG marker defs.
- Preview.svelte: swap <svg> for a <div> container; drop the Dead Ends
  checkbox (superseded by per-branch expand); pass new opts.
- styles.css: add .path-graph* + .pg-card* rules (warm palette, actor-
  typed border-left, stacked-shadow peek for .pg-card--has-hidden).
- app.svelte + .screen--wide: preview route breaks out of the 560px
  screen cap so the graph has room to breathe.

Also includes index.html at the repo root — the self-contained design
prototype the UX was iterated against. Easy to delete if not wanted.
@github-actions
Copy link
Copy Markdown

🔍 Preview deployed: https://db4e3cdb.toolpath.pages.dev

@eliot-emp eliot-emp merged commit 179cb2a into main Apr 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants