Skip to content

fix(desktop): use object-scale-down for inline markdown images - #4686

Merged
ngthuydiem merged 1 commit into
block:mainfrom
kushaim:fix/4384-markdown-image-scale
Oct 5, 2026
Merged

ngthuydiem merged 1 commit into
block:mainfrom
kushaim:fix/4384-markdown-image-scale

Conversation

@kushaim

@kushaim kushaim commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #4384.

A dim-less markdown image with no cached decode gets
DEFAULT_IMAGE_RESERVE = { height: 256, width: 384 } and
useFixedReserveBox: true in resolveImageReserveBox. The frame is
that big on first view, and the inline <img> uses object-contain
which scales UP to fill the frame — so a 46×20 shields badge renders
as a giant blurry block. The same message renders at the natural
size on the second view because rememberDecodedImageDimensions
populates the cache, but the inconsistency between first and
subsequent view is the bug.

Switches object-contain → object-scale-down on
ProgressiveImage.tsx's shared IMAGE_CLASS. Both object-contain
and object-scale-down scale down to fit, but only
object-scale-down also refuses to scale up — a small image now sits
centered in the reserve box on first view, never upscaled. The
layout-shift guarantee for large images is preserved (they still
scale down to fit the reserve), matching the issue's stated
constraint.

Chose option 2 ("Alternatively/minimally") from the issue over
option 1 because:

  • It's a one-class-name change with zero new state, zero new
    effects, and zero risk to the existing layout-shift guarantee
    that the surrounding useFrozenImageReserve is explicitly
    designed to preserve.
  • Option 1 (collapse the frame on decode) is the issue author's
    preferred direction but requires deciding whether the layout
    shift is acceptable shrink-only — a direction question that
    should be confirmed with the maintainer first. The issue
    explicitly says "Happy to open a PR for option 1 if the
    direction is acceptable" — that's the sign-off step, not
    this PR.

If maintainers want the full first-view-equals-second-view
behavior, option 1 is a follow-up that builds on this base.

Not added: a regression test. The current desktop test infra
(desktop/src/shared/ui/markdown/markdown.test.mjs and
siblings) doesn't cover ProgressiveImage directly; a
DOM-style snapshot would need a new test harness. The change
is one CSS class name; the visual regression is plain to
eyeball in the screenshots CI already captures.

Verified:

  • pnpm check (biome + file-sizes + px-text + pubkey-truncation) — clean
  • npx tsc --noEmit — clean

Fixes block#4384.

Switches object-contain to object-scale-down in ProgressiveImage.tsx's
shared IMAGE_CLASS so small dim-less badges don't upscale to fill the
fallback reserve box on first view. Both classes scale down to fit;
only object-scale-down also refuses to scale up.

Verified:
- pnpm check (biome + file-sizes + px-text + pubkey-truncation) — clean
- npx tsc --noEmit — clean

Option 1 from the issue (collapse the frame to the natural size on
decode) is a follow-up that requires maintainer sign-off on whether
a shrink-only layout shift is acceptable; the issue itself says
"Happy to open a PR for option 1 if the direction is acceptable".

Signed-off-by: kushaim <carlossilvajimenez@gmail.com>
@kushaim
kushaim requested a review from a team as a code owner August 4, 2026 08:20
Copilot AI lite review requested due to automatic review settings August 4, 2026 08:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ravarora2 ravarora2 added the triage-ready Appropriate for agentic review label Aug 5, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed at b6b8728e23a365d01e283d4b63608052ce3c5b84 on Wes's behalf.

No actionable findings. This is the intended minimal form of #4384's option 2: object-scale-down retains contain-style downscaling for content larger than its frame while preventing small dim-less images from being enlarged inside the frozen 384×256 first-view reserve. The image element, trigger hit area, reserve geometry, lightbox source box, thumbnail/full-image sequencing, and mosaic object-cover override remain unchanged.

Residual, non-blocking tradeoffs:

  • A first-view small dim-less image remains centered in a large blank/clickable reserve; a later mount can use cached intrinsic dimensions. The PR accurately discloses that layout-preserving tradeoff.
  • There is no direct first-view tiny-badge regression assertion.
  • desktop/src/shared/ui/markdown/utils.ts still says the caller letterboxes via object-contain; that comment is now stale, but does not affect behavior.

I did not duplicate the repository's CI-equivalent suites locally. CI was still running when this review was submitted, with no failures in the completed checks I inspected. This comment is a technical review, not an approval; Wes retains approval authority.

@ngthuydiem
ngthuydiem merged commit fcf5f04 into block:main Oct 5, 2026
26 checks passed
abipalli pushed a commit to abipalli/buzz that referenced this pull request Oct 7, 2026
…#4686)

Fixes block#4384.

A dim-less markdown image with no cached decode gets
`DEFAULT_IMAGE_RESERVE = { height: 256, width: 384 }` and
`useFixedReserveBox: true` in `resolveImageReserveBox`. The frame is
that big on first view, and the inline `<img>` uses `object-contain`
which scales UP to fill the frame — so a 46×20 shields badge renders
as a giant blurry block. The same message renders at the natural
size on the second view because `rememberDecodedImageDimensions`
populates the cache, but the inconsistency between first and
subsequent view is the bug.

Switches `object-contain` → `object-scale-down` on
`ProgressiveImage.tsx`'s shared `IMAGE_CLASS`. Both `object-contain`
and `object-scale-down` scale down to fit, but only
`object-scale-down` also refuses to scale up — a small image now sits
centered in the reserve box on first view, never upscaled. The
layout-shift guarantee for large images is preserved (they still
scale down to fit the reserve), matching the issue's stated
constraint.

Chose option 2 ("Alternatively/minimally") from the issue over
option 1 because:

- It's a one-class-name change with zero new state, zero new
  effects, and zero risk to the existing layout-shift guarantee
  that the surrounding `useFrozenImageReserve` is explicitly
  designed to preserve.
- Option 1 (collapse the frame on decode) is the issue author's
  preferred direction but requires deciding whether the layout
  shift is acceptable *shrink*-only — a direction question that
  should be confirmed with the maintainer first. The issue
  explicitly says "Happy to open a PR for option 1 if the
  direction is acceptable" — that's the sign-off step, not
  this PR.

If maintainers want the full first-view-equals-second-view
behavior, option 1 is a follow-up that builds on this base.

Not added: a regression test. The current desktop test infra
(`desktop/src/shared/ui/markdown/markdown.test.mjs` and
siblings) doesn't cover `ProgressiveImage` directly; a
DOM-style snapshot would need a new test harness. The change
is one CSS class name; the visual regression is plain to
eyeball in the screenshots CI already captures.

Verified:
- `pnpm check` (biome + file-sizes + px-text + pubkey-truncation) —
clean
- `npx tsc --noEmit` — clean

Signed-off-by: kushaim <carlossilvajimenez@gmail.com>
Co-authored-by: kushaim <carlossilvajimenez@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-ready Appropriate for agentic review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Markdown images without dim are upscaled to the fallback reserve box on first view (badges render huge)

5 participants