Skip to content

Enhance graph view navigation and label behavior - #23

Merged
JosephMaynard merged 16 commits into
masterfrom
feat/graph-view-upgrades
Mar 18, 2026
Merged

JosephMaynard merged 16 commits into
masterfrom
feat/graph-view-upgrades

Conversation

@JosephMaynard

@JosephMaynard JosephMaynard commented Mar 17, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add kinetic scrolling and stronger render layering in Graph View so selected nodes stay visually on top
  • improve graph labels with truncation, animated expansion on focused paths, and sample data updates for long-name testing
  • refine graph navigation with wider zoom-out limits, bounded panning, and workspace selector ordering that promotes Workspace root
  • regenerate bundled report assets to ship the updated report UI behavior

Testing

  • npm run build:report
  • npx tsc --noEmit
  • npx tsc
  • Full npm run build not run successfully because build:spdx attempted to reach raw.githubusercontent.com under restricted network access

Summary by CodeRabbit

  • New Features

    • Smooth inertial panning with kinetic throw, pan clamping, reduced‑motion support, and animated per‑node label rendering (progressive reveal/truncation)
  • Style

    • Updated editor color theme to a lighter green/teal palette; minor file formatting (newline)
  • Layout

    • Reworked graph overlay/top workspace layout and control placement for improved responsiveness; container class renamed (no behavior change)
  • Data

    • Enabled workspace-aware sample data and renamed several sample package identities
  • Documentation

    • Added TODOs outlining planned graph and CLI enhancements

@coderabbitai

coderabbitai Bot commented Mar 17, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds inertia-based panning and per-node label-character animation to the graph view, restructures overlay/workspace layout and CSS, enables workspaces and renames sample packages in sample data, updates VS Code colorCustomizations, and adds a TODOs.md with planned tasks.

Changes

Cohort / File(s) Summary
Graph Rendering & Interaction
report-ui/graphView.ts
Introduces per-node label state (labelGraphemes, targetLabelChars, renderLabelChars) and extensive inertia/panning logic (velocity sampling, start/stop/animate), pan/zoom clamps, reduced-motion handling, label truncation/formatting helpers, and integrates label-character animation into render/update loops.
UI Layout & Styling
report-ui/index.html, report-ui/style.css, src/report.ts
Renames overlay container class (graph-overlay-left → graph-workspace-wrap), consolidates overlays into a top overlay (.graph-overlay-top), updates responsive/layout CSS and related ID/class references/comments.
Sample Data & Workspace Support
report-ui/sample-data.json
Enables workspace mode and workspaces metadata (pnpm) for sample data; renames several top/root package identities to scoped @sample/... names and updates origins/workspace associations.
Configuration & Planning
.vscode/settings.json, TODOs.md
Updates VS Code colorCustomizations (dark green → lighter green/teal values) and adds newline; adds TODOs.md with Graph View and new-feature tasks (kinetic panning, label truncation, CLI explain command, summary for unreferenced dependencies).

Sequence Diagram

sequenceDiagram
    participant User as User Input
    participant Handler as Interaction Handler
    participant Inertia as InertiaState
    participant AnimLoop as Animation Loop
    participant Render as Canvas Renderer

    User->>Handler: Drag / Touch / Wheel input
    Handler->>Handler: update pan/zoom, reset velocity samples
    Handler->>Inertia: sample velocity / maybe startInertia()
    Inertia->>AnimLoop: mark inertia active

    loop While Inertia Active
        AnimLoop->>Inertia: animateInertia(delta)
        Inertia->>Handler: apply pan delta
        Handler->>Handler: clampPanToGraph()
        Handler->>Render: request render (use renderLabelChars)
        Render->>Render: draw nodes, edges and labels
        Inertia->>Inertia: apply friction & update velocity
    end

    Inertia->>AnimLoop: stopInertia()
    AnimLoop->>Render: final render
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰
I hop the graph where labels softly sway,
Inertia nudges me along the way.
Green hues brighten paths I roam,
Tiny letters find their home. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Enhance graph view navigation and label behavior' accurately summarizes the main changes across the changeset, which include kinetic scrolling enhancements, graph label improvements with truncation and animation, and refined navigation with better zoom and panning controls.
Docstring Coverage ✅ Passed Docstring coverage is 82.35% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/graph-view-upgrades
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
.vscode/settings.json (1)

15-15: Document the required extension or use built-in color settings.

windowColors.baseColor is an extension-contributed setting (e.g., from "Workspace Color Theme" or similar), not a built-in VS Code key. Contributors lacking this extension will see an unknown-setting warning. Either add a note to your setup documentation listing the required extension, or switch to the built-in workbench.colorCustomizations setting for color customization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vscode/settings.json at line 15, The setting "windowColors.baseColor" is
provided by an extension and will trigger unknown-setting warnings for
contributors without that extension; either add a short note in the project
setup/docs listing the required extension that provides windowColors.baseColor
(include the extension name and install instructions), or replace the
extension-specific key with VS Code's built-in "workbench.colorCustomizations"
entry to define the same color(s) so the repo settings work for everyone; update
the README or CONTRIBUTING to mention which approach you chose and where to find
the extension if you kept the extension-specific key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@report-ui/graphView.ts`:
- Around line 1947-1955: fit/reset doesn't account for right-hand labels drawn
by drawNodeLabel (which places text at node.renderX + node.renderRadius + 6
using formatGraphLabel); update the fit/pan calculations so bounds.maxX includes
the space needed for labels: for each node compute the label width (use the same
canvas context.measureText(formatGraphLabel(node)).width plus the 6px gap and
node.renderRadius as used in drawNodeLabel) and add that to the node's x extent
when computing bounds (or reserve a right-side margin equal to the max label
width) so nodes in the rightmost column are not fitted flush to the canvas edge
and labels remain visible.
- Around line 1557-1564: The animation loop currently eases node properties
every frame using LABEL_ANIMATION_EASING and updates
node.renderX/node.renderY/node.renderRadius/node.renderLabelChars even when
reducedMotionQuery indicates prefers-reduced-motion; modify the update in the
tick/animation function that contains the block using LABEL_ANIMATION_EASING and
the settled calculation to check reducedMotionQuery.matches and, if true, skip
easing and assign node.renderX=node.targetX, node.renderY=node.targetY,
node.renderRadius=node.targetRadius, node.renderLabelChars=node.targetLabelChars
(and mark settled accordingly) so focus/hover changes take effect instantly
without per-frame transitions.

In `@report-ui/sample-data.json`:
- Around line 19-53: The workspace "directExternal" counts are inconsistent with
the dependency origins—recompute each workspacePackages[].directExternal
(runtime/dev) by scanning the dependency entries' usage.direct, scope, and
origins.workspaces fields rather than hardcoding values: for each workspace
(e.g., demo-app-web, demo-app-admin, demo-package-ui, demo-package-utils) count
dependencies whose origins.workspaces includes that workspace and whose
usage.direct is true, incrementing runtime or dev based on scope, and update the
directExternal object accordingly so the workspace summary and per-dependency
origins (usage.direct/scope/origins.workspaces) agree.
- Around line 63-64: The dependencies object keys must match the corresponding
package.id values to avoid dangling references; update the dependency map keys
(e.g., replace old keys like "chalk@5.3.0", "ansi-styles@6.2.1" with the new
package ids such as "@sample/terminal-color-management-foundation@5.3.0") so
they align with each package's "package.id" field, and ensure related arrays
like "topParentPackages" use the same ids consistently; locate and update the
entries referenced in the review (the dependency objects around the package with
package.id "@sample/terminal-color-management-foundation@5.3.0" and the other
occurrences noted) so all id-based lookups (package.id, dependencies keys,
topParentPackages) are identical.

In `@report-ui/style.css`:
- Around line 913-925: The toolbar (.graph-overlay-top) can wrap and exceed its
min-height, but the controls (.graph-controls) are positioned with a fixed top
(e.g., top: 62px) and higher z-index causing overlap; change .graph-controls to
be positioned relative to the toolbar height instead of a hard-coded top (for
example by placing .graph-controls inside the same layout flow as
.graph-overlay-top, using position: static/relative with margin or using CSS
variables set from the toolbar height, or by calculating top from
.graph-overlay-top's rendered height) so the controls move down when
.graph-overlay-top wraps (also update the other hard-coded top usages for
.graph-controls referenced elsewhere).

---

Nitpick comments:
In @.vscode/settings.json:
- Line 15: The setting "windowColors.baseColor" is provided by an extension and
will trigger unknown-setting warnings for contributors without that extension;
either add a short note in the project setup/docs listing the required extension
that provides windowColors.baseColor (include the extension name and install
instructions), or replace the extension-specific key with VS Code's built-in
"workbench.colorCustomizations" entry to define the same color(s) so the repo
settings work for everyone; update the README or CONTRIBUTING to mention which
approach you chose and where to find the extension if you kept the
extension-specific key.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 54bfd8fd-cf6f-4455-a24f-b453ee4e52b8

📥 Commits

Reviewing files that changed from the base of the PR and between 07ee243 and 563a457.

⛔ Files ignored due to path filters (4)
  • dist/report-assets.js is excluded by !**/dist/**
  • dist/report.js is excluded by !**/dist/**
  • report-ui/dist/report.css is excluded by !**/dist/**
  • report-ui/dist/report.iife.js is excluded by !**/dist/**
📒 Files selected for processing (8)
  • .vscode/settings.json
  • TODOs.md
  • report-ui/graphView.ts
  • report-ui/index.html
  • report-ui/sample-data.json
  • report-ui/style.css
  • src/report-assets.ts
  • src/report.ts

Comment thread report-ui/graphView.ts
Comment thread report-ui/graphView.ts
Comment thread report-ui/sample-data.json
Comment on lines +63 to +64
"id": "@sample/terminal-color-management-foundation@5.3.0",
"name": "@sample/terminal-color-management-foundation",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep the dependency map keys and package.id aligned.

These entries were renamed in package.id, but the enclosing dependencies object is still keyed by the old ids ("chalk@5.3.0", "ansi-styles@6.2.1", etc.). At the same time, references like topParentPackages now use the new @sample/... id at Lines 183-189. That leaves the sample data with two competing identifiers for the same node and can turn id-based lookups into dangling references. Rename the object keys too, or keep the old ids everywhere.

Also applies to: 126-127, 183-189, 779-780, 849-850

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/sample-data.json` around lines 63 - 64, The dependencies object
keys must match the corresponding package.id values to avoid dangling
references; update the dependency map keys (e.g., replace old keys like
"chalk@5.3.0", "ansi-styles@6.2.1" with the new package ids such as
"@sample/terminal-color-management-foundation@5.3.0") so they align with each
package's "package.id" field, and ensure related arrays like "topParentPackages"
use the same ids consistently; locate and update the entries referenced in the
review (the dependency objects around the package with package.id
"@sample/terminal-color-management-foundation@5.3.0" and the other occurrences
noted) so all id-based lookups (package.id, dependencies keys,
topParentPackages) are identical.

Comment thread report-ui/style.css

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
report-ui/sample-data.json (2)

63-64: ⚠️ Potential issue | 🟠 Major

Align the renamed ids with the canonical dependency keys.

These package.id / topParentPackages updates create a second identifier for the same node because the enclosing dependencies entries are still keyed by the old ids. Any lookup keyed by the new @sample/...@version strings will miss the backing record.

🧩 Suggested key alignment
- "chalk@5.3.0": {
+ "@sample/terminal-color-management-foundation@5.3.0": {

- "ansi-styles@6.2.1": {
+ "@sample/console-formatting-token-palette@6.2.1": {

- "good-license-lib@1.2.3": {
+ "@sample/highly-compliant-open-source-license-demonstration-library@1.2.3": {

- "bad-license-lib@0.4.0": {
+ "@sample/poorly-documented-license-mismatch-demonstration-package@0.4.0": {

Also applies to: 126-127, 183-189, 779-780, 849-850

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/sample-data.json` around lines 63 - 64, The package entries renamed
their "id" fields (e.g. "@sample/terminal-color-management-foundation@5.3.0")
but the surrounding dependencies object still uses the old keys, creating
duplicate/lookup mismatches; update the dependencies map keys to exactly match
the new package.id strings (and ensure any topParentPackages references use the
same canonical ids) so lookups by the new "@sample/...@version" identifiers
resolve the single backing record.

102-106: ⚠️ Potential issue | 🟡 Minor

Fix the impossible workspace ancestry in this fixture.

@sample/console-formatting-token-palette@6.2.1 is marked as originating from demo-app-web, but its only listed root/parent package is @sample/terminal-color-management-foundation@5.3.0, whose own workspace origins are demo-app-admin, demo-package-ui, and demo-package-utils. This sample graph is now internally inconsistent.

Also applies to: 177-189

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/sample-data.json` around lines 102 - 106, The fixture has an
inconsistent workspace ancestry: the package
"@sample/console-formatting-token-palette@6.2.1" claims origin "demo-app-web"
but its parent "@sample/terminal-color-management-foundation@5.3.0" lists only
"demo-app-admin", "demo-package-ui", and "demo-package-utils"; update the
sample-data.json fixture so the workspaces arrays are consistent — either add
"demo-app-web" to the "workspaces" array of
"@sample/terminal-color-management-foundation@5.3.0" or change the origin of
"@sample/console-formatting-token-palette@6.2.1" to one of the existing roots;
apply the same fix to the duplicate block around the later occurrence (the block
referenced at lines 177-189).
report-ui/graphView.ts (1)

925-955: ⚠️ Potential issue | 🟠 Major

Use one stable content-bounds model for fit and pan clamping.

This still is not fully closed: updateFitMetrics() now reserves some label width, but clampPanToGraph() still clamps against currentGraph.bounds, which only tracks node centers. Because the fit path also measures formatGraphLabel(node), the first fit only sees the shorter pre-animation label. Long labels can still end up clipped, and once clipped the pan bounds will not let users bring them fully back into view.

Also applies to: 1097-1120

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/graphView.ts` around lines 925 - 955, clampPanToGraph() uses
currentGraph.bounds (node centers) while updateFitMetrics() computes a different
content footprint including label widths via formatGraphLabel(node); unify them
by computing a single stable content-bounds (including reserved label extents)
inside updateFitMetrics() (or a new getContentBoundsForFit()) and have
clampPanToGraph() read and clamp against that same bounds model instead of
currentGraph.bounds; update any other pan-clamping call sites that use the old
bounds (the duplicated clamp logic later in the file) to use the unified
content-bounds so long labels are measured once and never get clipped after
fit/animation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@report-ui/graphView.ts`:
- Around line 1995-2012: The labels are being drawn in a separate global pass
which breaks the priority stacking; modify the loop that iterates priorities so
each priority group draws body, rings, and then labels for that priority (i.e.,
inside the for (const priority of [0,1,2]) loop call drawNodeBody(node),
drawVulnerabilityRings(node), then drawNodeLabel(node) for nodes with matching
priority), and ensure context.textBaseline, context.font (GRAPH_LABEL_FONT) and
context.fillStyle = labelColor are set before the per-priority label draws so
label styling applies correctly; update references to renderNodes, drawNodeBody,
drawVulnerabilityRings, and drawNodeLabel accordingly.

---

Duplicate comments:
In `@report-ui/graphView.ts`:
- Around line 925-955: clampPanToGraph() uses currentGraph.bounds (node centers)
while updateFitMetrics() computes a different content footprint including label
widths via formatGraphLabel(node); unify them by computing a single stable
content-bounds (including reserved label extents) inside updateFitMetrics() (or
a new getContentBoundsForFit()) and have clampPanToGraph() read and clamp
against that same bounds model instead of currentGraph.bounds; update any other
pan-clamping call sites that use the old bounds (the duplicated clamp logic
later in the file) to use the unified content-bounds so long labels are measured
once and never get clipped after fit/animation.

In `@report-ui/sample-data.json`:
- Around line 63-64: The package entries renamed their "id" fields (e.g.
"@sample/terminal-color-management-foundation@5.3.0") but the surrounding
dependencies object still uses the old keys, creating duplicate/lookup
mismatches; update the dependencies map keys to exactly match the new package.id
strings (and ensure any topParentPackages references use the same canonical ids)
so lookups by the new "@sample/...@version" identifiers resolve the single
backing record.
- Around line 102-106: The fixture has an inconsistent workspace ancestry: the
package "@sample/console-formatting-token-palette@6.2.1" claims origin
"demo-app-web" but its parent
"@sample/terminal-color-management-foundation@5.3.0" lists only
"demo-app-admin", "demo-package-ui", and "demo-package-utils"; update the
sample-data.json fixture so the workspaces arrays are consistent — either add
"demo-app-web" to the "workspaces" array of
"@sample/terminal-color-management-foundation@5.3.0" or change the origin of
"@sample/console-formatting-token-palette@6.2.1" to one of the existing roots;
apply the same fix to the duplicate block around the later occurrence (the block
referenced at lines 177-189).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b562033-80cb-4b85-a39f-14aacc7308f7

📥 Commits

Reviewing files that changed from the base of the PR and between 563a457 and 38099c1.

⛔ Files ignored due to path filters (3)
  • dist/report-assets.js is excluded by !**/dist/**
  • report-ui/dist/report.css is excluded by !**/dist/**
  • report-ui/dist/report.iife.js is excluded by !**/dist/**
📒 Files selected for processing (5)
  • .vscode/settings.json
  • report-ui/graphView.ts
  • report-ui/sample-data.json
  • report-ui/style.css
  • src/report-assets.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .vscode/settings.json

Comment thread report-ui/graphView.ts
Comment on lines +1995 to 2012
for (const priority of [0, 1, 2]) {
renderNodes.forEach(({ node, priority: nodePriority }) => {
if (nodePriority !== priority) return;
drawNodeBody(node);
});

renderNodes.forEach(({ node, priority: nodePriority }) => {
if (nodePriority !== priority) return;
drawVulnerabilityRings(node);
});
}

context.textBaseline = "middle";
context.font = GRAPH_LABEL_FONT;
context.fillStyle = labelColor;
renderNodes.forEach(({ node }) => {
drawNodeLabel(node);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Draw labels in the same priority pass as their nodes.

The new node/ring passes honor the priority sort, but labels are painted afterward in one global pass. A long low-priority label can still cross over the focused node and weaken the “selected on top” behavior.

🧱 Suggested layering change
-    for (const priority of [0, 1, 2]) {
-      renderNodes.forEach(({ node, priority: nodePriority }) => {
-        if (nodePriority !== priority) return;
-        drawNodeBody(node);
-      });
-
-      renderNodes.forEach(({ node, priority: nodePriority }) => {
-        if (nodePriority !== priority) return;
-        drawVulnerabilityRings(node);
-      });
-    }
-
     context.textBaseline = "middle";
     context.font = GRAPH_LABEL_FONT;
     context.fillStyle = labelColor;
-    renderNodes.forEach(({ node }) => {
-      drawNodeLabel(node);
-    });
+    for (const priority of [0, 1, 2]) {
+      renderNodes.forEach(({ node, priority: nodePriority }) => {
+        if (nodePriority !== priority) return;
+        drawNodeBody(node);
+      });
+
+      renderNodes.forEach(({ node, priority: nodePriority }) => {
+        if (nodePriority !== priority) return;
+        drawVulnerabilityRings(node);
+      });
+
+      renderNodes.forEach(({ node, priority: nodePriority }) => {
+        if (nodePriority !== priority) return;
+        drawNodeLabel(node);
+      });
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/graphView.ts` around lines 1995 - 2012, The labels are being drawn
in a separate global pass which breaks the priority stacking; modify the loop
that iterates priorities so each priority group draws body, rings, and then
labels for that priority (i.e., inside the for (const priority of [0,1,2]) loop
call drawNodeBody(node), drawVulnerabilityRings(node), then drawNodeLabel(node)
for nodes with matching priority), and ensure context.textBaseline, context.font
(GRAPH_LABEL_FONT) and context.fillStyle = labelColor are set before the
per-priority label draws so label styling applies correctly; update references
to renderNodes, drawNodeBody, drawVulnerabilityRings, and drawNodeLabel
accordingly.

@coderabbitai

coderabbitai Bot commented Mar 17, 2026 •

Copy link
Copy Markdown
Contributor

Note

Docstrings generation - SUCCESS
Generated docstrings and committed to branch feat/graph-view-upgrades (commit: 766d33227879f32220f4fabce5e037c0adcae527)

Docstrings generation was requested by @JosephMaynard.

The following files were modified:

* `report-ui/graphView.ts`
* `src/report.ts`

These file types are not supported:
* `.vscode/settings.json`
* `TODOs.md`
* `report-ui/index.html`
* `report-ui/sample-data.json`
* `report-ui/style.css`

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
report-ui/graphView.ts (1)

2158-2165: Use GRAPH_LABEL_GAP in drawNodeLabel instead of a magic number.

updateFitMetrics uses GRAPH_LABEL_GAP, but label rendering uses a hardcoded 6 (Line 2164). Keeping both paths on the same constant prevents future fit/render drift.

Proposed patch
-      context.fillText(
-        label,
-        node.renderX + node.renderRadius + 6,
-        node.renderY,
-      );
+      context.fillText(
+        label,
+        node.renderX + node.renderRadius + GRAPH_LABEL_GAP,
+        node.renderY,
+      );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/graphView.ts` around lines 2158 - 2165, Replace the hardcoded label
offset in drawNodeLabel with the existing GRAPH_LABEL_GAP constant so rendering
uses the same gap as updateFitMetrics; locate drawNodeLabel (which calls
formatGraphLabel and nodeOpacity) and change the x offset calculation from
"node.renderRadius + 6" to "node.renderRadius + GRAPH_LABEL_GAP" and ensure
GRAPH_LABEL_GAP is imported/available in this module.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@report-ui/graphView.ts`:
- Around line 2158-2165: Replace the hardcoded label offset in drawNodeLabel
with the existing GRAPH_LABEL_GAP constant so rendering uses the same gap as
updateFitMetrics; locate drawNodeLabel (which calls formatGraphLabel and
nodeOpacity) and change the x offset calculation from "node.renderRadius + 6" to
"node.renderRadius + GRAPH_LABEL_GAP" and ensure GRAPH_LABEL_GAP is
imported/available in this module.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 854042f7-4553-4144-ab17-b961a810bfc9

📥 Commits

Reviewing files that changed from the base of the PR and between 38099c1 and 766d332.

📒 Files selected for processing (2)
  • report-ui/graphView.ts
  • src/report.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/report.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
report-ui/graphView.ts (1)

1235-1237: Unused graphWidth variable.

graphWidth is computed on line 1235 but never referenced. The fit zoom calculation on line 1237 correctly uses contentMaxX - bounds.minX instead. Consider removing the dead variable.

🧹 Suggested cleanup
-    const graphWidth = Math.max(1, bounds.maxX - bounds.minX);
     const graphHeight = Math.max(1, bounds.maxY - bounds.minY);
     const fitZoomX = width / Math.max(1, contentMaxX - bounds.minX);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/graphView.ts` around lines 1235 - 1237, Remove the unused local
variable graphWidth: it’s computed as const graphWidth = Math.max(1, bounds.maxX
- bounds.minX) but never used; keep graphHeight and fitZoomX (which uses
contentMaxX - bounds.minX) intact and delete the graphWidth declaration to
eliminate the dead variable and tidy the function where graphWidth is declared.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@report-ui/graphView.ts`:
- Around line 1235-1237: Remove the unused local variable graphWidth: it’s
computed as const graphWidth = Math.max(1, bounds.maxX - bounds.minX) but never
used; keep graphHeight and fitZoomX (which uses contentMaxX - bounds.minX)
intact and delete the graphWidth declaration to eliminate the dead variable and
tidy the function where graphWidth is declared.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59e66d96-cdfd-4476-9bd2-d3fab07fcc6b

📥 Commits

Reviewing files that changed from the base of the PR and between 766d332 and 9a0c106.

⛔ Files ignored due to path filters (1)
  • dist/report.js is excluded by !**/dist/**
📒 Files selected for processing (1)
  • report-ui/graphView.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
report-ui/graphView.ts (1)

1378-1378: Consider using Intl.Segmenter for proper grapheme segmentation.

Array.from(string) splits by Unicode code points, not graphemes. For strings with combining characters or emoji (e.g., "café" with combining accent, or emoji like "👨‍👩‍👧‍👦"), this could produce incorrect truncation. While unlikely for typical package names, using Intl.Segmenter would be more robust.

♻️ Optional: Use Intl.Segmenter for true grapheme segmentation
- const labelGraphemes = Array.from(dataset.dependencies[slug].name);
+ const labelGraphemes = typeof Intl?.Segmenter === "function"
+   ? [...new Intl.Segmenter().segment(dataset.dependencies[slug].name)].map(s => s.segment)
+   : Array.from(dataset.dependencies[slug].name);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@report-ui/graphView.ts` at line 1378, Replace the simple Array.from(...)
grapheme splitting with Unicode-aware segmentation: use Intl.Segmenter (if
available) to segment dataset.dependencies[slug].name into grapheme clusters for
labelGraphemes so combining marks and emoji are handled correctly, and fall back
to Array.from(...) when Intl.Segmenter is undefined; update the logic around
labelGraphemes in graphView.ts accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@report-ui/graphView.ts`:
- Line 1378: Replace the simple Array.from(...) grapheme splitting with
Unicode-aware segmentation: use Intl.Segmenter (if available) to segment
dataset.dependencies[slug].name into grapheme clusters for labelGraphemes so
combining marks and emoji are handled correctly, and fall back to
Array.from(...) when Intl.Segmenter is undefined; update the logic around
labelGraphemes in graphView.ts accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 53468428-068c-4b6a-9f0a-9bcba470dd52

📥 Commits

Reviewing files that changed from the base of the PR and between 9a0c106 and 83203e6.

⛔ Files ignored due to path filters (2)
  • dist/report-assets.js is excluded by !**/dist/**
  • report-ui/dist/report.iife.js is excluded by !**/dist/**
📒 Files selected for processing (2)
  • report-ui/graphView.ts
  • src/report-assets.ts

@JosephMaynard
JosephMaynard merged commit dc5390a into master Mar 18, 2026
1 check passed
@JosephMaynard
JosephMaynard deleted the feat/graph-view-upgrades branch March 18, 2026 10:17
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.

1 participant