aws / aws/graph-explorer

Non-square icons are squashed instead of scaled to fit

Open
#2,108 0 comments 0 reactions 0 assignees View on GitHub
customization internal usability
Dominant language
TypeScript
Stars
481
Forks
108
Avg merge
6d 8h
Merged PRs (30d)
5

Description

A node icon that is not square is stretched into a square rather than scaled down to fit, so it renders distorted. Affects both the graph canvas and the DOM surfaces, consistently.

## Reproduce

1. Style a node type with a custom uploaded raster icon whose width and height differ — a wide logo shows it clearly.
2. Look at the node on the graph canvas, and at the same node type in a search result row.

The icon fills a square box, distorted. Expected: scaled down to fit the icon box, keeping its aspect ratio.

## Why it happens

**Canvas.** `components/Graph/styles/defaultNodeStyle.ts` sets:

```ts
backgroundFit: "none",
backgroundWidth: "60%",
backgroundHeight: "60%",
```

Per cytoscape 3.34.0 `drawInscribedImage`, `background-width`/`-height` **override** the image’s natural dimensions, and `background-fit` then scales whatever those left:

```js
var w = imgW, h = imgH;
if (background-width !== auto) w = pct * nodeTW; // 0.6 * 24 = 14.4
if (background-height !== auto) h = pct * nodeTH; // 0.6 * 24 = 14.4
if (fit === "contain") { var scale = Math.min(nodeTW / w, nodeTH / h); w *= scale; h *= scale; }
```

So both axes are forced to 14.4 and the image is stretched into a square.

**`background-fit: contain` does not fix this** — it runs *after* the override, when `w` and `h` are already equal, so it just scales the squashed square up to fill the node. Verified in headless Chrome against real cytoscape 3.34.0.

**DOM.** `components/VertexIcon.tsx` renders ``. Forcing both dimensions with the default `object-fit: fill` stretches the image the same way.

`VertexSymbol` is already correct — its `` carries `preserveAspectRatio="xMidYMid meet"`.

## Fix sketch

There is no configuration-only fix: cytoscape cannot fit an image to a box and preserve its ratio at the same time, so the intrinsic ratio has to be known before the style is generated.

1. Measure the raster’s natural size when it resolves (`core/icons/iconRegistry.ts`) and carry the aspect ratio on the resolved icon.
2. Compute `background-width`/`background-height` from it, shrinking the shorter axis so the icon fits the 60% box instead of stretching to it — e.g. a 4:1 image becomes `60%` / `15%`.
3. `VertexIcon`: add `object-contain` to the ``.
4. Generated SVG icons need nothing — they carry a viewBox and letterbox themselves.

Known costs, which is why this was split out rather than bundled into #2102:

- Raster resolution becomes asynchronous, where today the url needs no work.
- Adds an image-load failure mode, needing a fallback to square.
- No test environment loads images, so measuring never settles without an `Image` test double in `setupTests.ts` — which changes the environment for every test file.
- `useBackgroundImageMap` has to return dimensions alongside the image, so its return type and name both change, rippling into `useGraphStyles`.

## Notes

Pre-existing behavior, unchanged by the icon pipeline rework in #2102 — `defaultNodeStyle.ts` has carried these values since before that branch. Distinct from #2105, which is about *recoloring* custom SVG icons rather than sizing them.

---

> [!IMPORTANT]
> Internal only — this issue is maintained by the core team and is not accepting external contributions.

Contributor guide

Open the contributing guide

Research direction

Start with components/Graph/styles/defaultNodeStyle.ts and components/VertexIcon.tsx, then trace icon resolution through core/icons/iconRegistry.ts, useBackgroundImageMap, and useGraphStyles. Review setupTests.ts for the image-loading test implications. Done means non-square raster icons preserve their aspect ratio on both the graph canvas and DOM search rows, with a fallback for failed image resolution and coverage for the changed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.