# fix\(web\): size the chat image slot from server-reported dimensions · PR \#10200 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10200)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: media-dims/web

Target branch: media-dims/mobile

Head commit: d18793ccd7ee493069b937119ea852088ba12cf3

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/10200)

[Commits](https://git.cafe/pingdotgg/t3code/pull/10200/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/10200/diffs?format=markdown)

## Description

---

Stack 3/3 (#10201). Depends on #10198.

## Problem

After #9938 a workspace image on web still moved the rows below it once: a portrait screenshot grew past its 16:9 slot when it decoded.

## Fix

`ChatMarkdownAssetImage` applies the server's `imageDimensions` (#10198) through the existing `authoredImageSizeStyle`, so the slot is the image's final box from the moment the URL resolves. An authored `width`/`height` still wins; a caller's cap (the viewed-image row's `maxHeight: 16rem`) layers on top rather than shadowing the dimensions.

## Evidence

Cold thread mount with image responses delayed 4 s, `layout-shift` observer armed before mount (same harness as #9938):

| | #9938 | this PR |
|---|---|---|
| Media layout-shift entries | 1 (0.013 — portrait growing past 16:9) | **0** |

The only remaining entry on the page is the composer resizing, unrelated to media.

## Verification

- `ChatMarkdown.workspace-images.test.tsx`: slot is sized from server dimensions (`width: 720px; aspect-ratio: 720 / 1400`); authored size overrides server dimensions. 32 passed.
- `apps/web` typecheck clean.
- In-browser: portrait image renders with `aspect-ratio: 720 / 1400` on the slot and the settled `<img>`; a 16rem `maxHeight` cap yields a 247×256 box.

Model: Claude Fable 5 · Harness: Claude Code in T3 Code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Size chat asset images from server-reported dimensions
> - `ChatMarkdownAssetImage` now reads reported width and height from successful asset URL loads and derives inline width, aspect ratio, and a height-derived max-width
> - `authoredImageSizeStyle` gains an optional height-cap argument (default 30rem); when both dimensions are present the cap is folded into the max-width calculation
> - `PlainWorkEntryRow` in [MessagesTimeline.tsx](https://github.com/pingdotgg/t3code/pull/10200/files#diff-f2a34c4ad8d2b68c45657dbdcbf14afac4ea93e1fbd37007aaa2ccb8b41d2588) switches from an inline `max-height` style to the new `maxHeightRem` prop, keeping the 16rem value
> - Explicit incoming `style` props still take precedence; callers without dimensions can still apply a custom rem height cap as a fallback
> - Risk: asset images without server-reported dimensions no longer get a computed aspect ratio — they fall back to the height-cap path only, which may shift layout for previously auto-sized images in [ChatMarkdown.tsx](https://github.com/pingdotgg/t3code/pull/10200/files#diff-70b5bb003244414202733c39403081a84415e222927a1ef415599958115c0c05)
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized d18793c.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
