Skip to content

Render VertexIcon through the icon registry and drop react-inlinesvg - #2423

Open
kmcginnes wants to merge 9 commits into
mainfrom
render-vertex-icon-through-registry
Open

kmcginnes wants to merge 9 commits into
mainfrom
render-vertex-icon-through-registry

Conversation

@kmcginnes

Copy link
Copy Markdown
Collaborator

Summary

VertexIcon was the last place a custom SVG icon was turned into markup outside the icon registry. It now renders through the registry as an image, like every other icon surface, so there is one decode and sanitize path and react-inlinesvg is gone.

 VertexIcon
   lucide  → DynamicIcon (inline, inherits color)
-  svg     → react-inlinesvg: decode + sanitize, inlined into the page
+  svg     → useResolvedIcon → <img src={toIconImageUrl(icon, color)}>
   raster  → <img src>
  • Fidelity: the SVG keeps its own <style>, gradients and filters, scoped to the icon. react-inlinesvg decoded base64 without reading it as UTF-8, so non-ASCII text came out as mojibake; the registry decodes it correctly.
  • Recolor cost: toIconImageUrl and toCanvasBackgroundImage share one least-recently-used cache keyed by resolved icon, then color, holding up to 256 colors per icon. A render pass over thousands of icons costs one parse per icon and color, and none on later passes.
  • List rows: a same-size placeholder holds each icon's space while it resolves or when an SVG is unusable, so rows do not shift. Lucide icons use an <svg> placeholder so the parent's icon sizing applies to it.
  • Removed: react-inlinesvg, the unused SVG fetch in drawImage, colorizeSvg, and the (icon, color) dedupe in useBackgroundImageMap that the cache replaces.
  • Docs: the icon registry ADR and GLOSSARY.md now describe every surface as an image, and the stale inline-SVG wording in the styling file notes is gone.

Evidence

Before: custom SVG icons were inlined into the page, and non-ASCII text in them rendered garbled.

After: custom SVGs render as images: a non-ASCII text icon on airport, a width and height only SVG with no viewBox on continent, a raster on ExampleNode, and Lucide icons, in the filter list and on the canvas.

Entities Filter list and graph canvas showing custom SVG, raster and Lucide icons

✓ keeps at most 256 colors per icon, dropping the least recently used
✓ serves a full cyclic pass over 200 colors from the cache
✓ parses an icon once however many times it is drawn in one color
✓ renders a custom svg as an image, keeping it out of the live DOM
✓ decodes non-ascii svg text as utf-8

Verified live: in Chrome against a Neptune air-routes database with a 10,050-type schema, across the filter list, connection type list, search results, neighbors list, legend and canvas.

  • Setting 6 new colors cost 6 parses and the same 6 again cost 0. Dragging the color picker through 60 positions cost 31, with no repeated color.
  • Heap size did not grow across repeated flows.
  • No fetch() of data: urls and no external requests.
  • The real modules also ran in Firefox and Safari.
  • A color change still freezes the main thread for about 0.75 to 1 s on that schema. Roughly 5 of the 13.8 s trace was cytoscape rebuilding its stylesheet, and the icon code was about 0.1 s, so this change does not move it.

Merge Danger

Door: two-way

Stored icons and the styling file format are unchanged, so reverting restores the old rendering.

Impact: icons

A custom SVG that depended on being inlined, such as one relying on page CSS, now renders as an image and no longer sees it. Raster and Lucide icons render as before.

Related

This branch has not been deployed

No deployments
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.

Render VertexIcon through the icon registry and drop react-inlinesvg

1 participant