Skip to content

fix(webui): stop the download count spilling out of the extension card - #2178

Merged
netomi merged 2 commits into
mainfrom
fix/card-footer-overflow
Sep 8, 2026
Merged

netomi merged 2 commits into
mainfrom
fix/card-footer-overflow

Conversation

@netomi

@netomi netomi commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Reported while testing search results: on an extension with both reviews and a large download count — redhat.java on open-vsx.org — the download count overflows the card.

Why it overflows

The footer is a space-between flex row of two groups, and neither can give way:

  • Left — ExtensionRatingStars always renders five icons (extension-rating-stars.tsx:42, [1,2,3,4,5].map(getStar)). Flex items default to min-width: auto, and a row of icons has nothing to shrink.
  • Right — the download group sets flexShrink: 0.

Once the two intrinsic widths exceed the card, nothing yields and the count is pushed past the edge. redhat.java hits it squarely: rating 5.0 (five filled stars), 16 reviews, and 41,183,269 downloads → 41M in a monospace font. That's the "reviews and lots of downloads" combination — it needs both halves at their widest.

The only relief was a container query hiding the review count below 134px. That's one fixed number guarding content whose width varies with the download string, which is why 41M spills where 12K does not.

The change

The rating is now one star and the number. Five icons are an intrinsic width that cannot shrink; ★ 5.0 is bounded, roughly half as wide, and arguably says more than a row of icons the reader has to count. An extension nobody has reviewed shows nothing at all, rather than five grey stars claiming the width to state a score that does not exist.

The row gets the shrink discipline the name row above it already has — that row uses overflow: hidden, minWidth: 0 and explicit shrink priorities; the footer was the one row that never got it. Now: a gap so the groups cannot touch, minWidth: 0 + overflow: hidden on the rating so it clips, flexShrink: 0 kept on the count.

Which extension is more popular is what the eye compares across a grid of these, so the download count is never what gives way — the rating beside it is. Overflow becomes structurally impossible rather than tuned away, and the 134px magic number is deleted rather than retuned.

The loading skeleton was drawing five stars too, so it now matches the footprint the real card has.

ExtensionRatingStars itself is untouched — the detail page and the reviews list have room for five stars and still use it.

Testing

Three tests in a new extension-card.spec.tsx: the rating renders as exactly one StarIcon plus 5.0 and (16); the download count survives beside it; and an unreviewed extension renders no star at all.

Full webui suite green (289 tests, 56 files), tsc --noEmit and yarn lint clean.

Not verified in a browser. This build image has no engine Playwright supports (Playwright does not support chromium on ubuntu26.04-x64, and there's no chromium package), so I could not render the before or after. That shaped the fix: it's built so that overflow cannot happen for any content width, rather than tuned to measurements I couldn't take. The visual change — one star instead of five — is worth a look on a real page before merging, particularly at the narrow end of the grid and on a card with no reviews.

🤖 Generated with Claude Code

The card footer is a space-between row of two groups, and neither could give
way. On the left ExtensionRatingStars always draws five icons - flex items
have min-width: auto, and a row of icons has nothing to shrink - and on the
right the download count sets flexShrink: 0. Once the two intrinsic widths
exceeded the card, nothing yielded and the count was pushed past its edge.
redhat.java hits it squarely: 5.0 stars, 16 reviews and 41M downloads, which
is the "reviews and lots of downloads" combination that needs both halves at
their widest.

The only relief was a container query hiding the review count below 134px -
one fixed number guarding content whose width varies with the download string,
which is why "41M" spills where "12K" does not.

Show the rating as one star and the number instead. Five icons are an
intrinsic width that cannot shrink; a star and "5.0" is bounded, roughly half
as wide, and says more than a row of icons somebody has to count. An
extension nobody has reviewed now shows nothing rather than five grey stars
claiming the width to state a score that does not exist.

And give the row the shrink discipline the name row above it already has: a
gap so the groups cannot touch, minWidth: 0 and overflow: hidden on the
rating so it clips, flexShrink: 0 kept on the count. Which extension is more
popular is what the eye compares across a grid of these, so that number stays
whole and the rating beside it is what gives. Overflow is now structurally
impossible rather than merely tuned away, and the 134px magic number is gone.

Not verified in a browser: this image has no engine Playwright supports, so
the fix is built to need no measurement rather than to match one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netomi

netomi commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Before:

image

After:

image

@netomi

netomi commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author
image

vs.

image

@netomi
netomi requested a review from gnugomez September 7, 2026 18:40

Copilot AI 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.

🟡 Changes recommended

The new unit tests hard-code locale-dependent compact-number strings (and the new rating formatting isn’t locale-aware), which can cause flaky CI and inconsistent numeric rendering across locales.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adjusts the ExtensionCard footer layout to prevent large download counts from overflowing the card in narrow grid layouts by shrinking/clipping the rating side instead of allowing the downloads side to spill.

Changes:

  • Replaces the footer’s 5-star rating widget with a single star icon plus numeric rating and review count, and adds flex/overflow constraints to make overflow structurally impossible.
  • Updates the loading skeleton footer to match the new rating footprint.
  • Adds unit tests covering the new footer rating rendering rules and ensuring the download count still renders alongside it.
File summaries
File Description
webui/src/components/extension-card.tsx Updates footer flex behavior and rating display to avoid download count overflow; aligns skeleton footer footprint.
webui/test/unit/components/extension-card.spec.tsx Adds unit tests validating the new footer rating/download rendering behavior.
Review details

Suppressed comments (1)

webui/test/unit/components/extension-card.spec.tsx:74

  • This expectation hard-codes '1.2K', but compact number formatting is locale-dependent (suffix, decimal separator, spacing). Using an Intl formatter in the assertion makes the test stable across locales while still verifying that the download count is rendered.
        expect(screen.getByText('1.2K')).toBeInTheDocument();
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread webui/src/components/extension-card.tsx Resolved
@gnugomez

gnugomez commented Sep 8, 2026

Copy link
Copy Markdown
Member

when we spotted this issue first one of my ideas was to collapse the stars into a number as well, I didn't did that just because I wasn't sure we wanted to move away from that

@netomi

netomi commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

its really awful right now and we need to collapse the stars in the card view as I do not have any other idea. In the extension detail view, the stars are still not collapsed and there its fine.

Comment thread webui/src/components/extension-card.tsx Resolved
… cell

Review feedback.

toFixed(1) always emits a '.', while every other number on the card goes
through Intl - so a German viewer saw "5.0" beside "41 Mio.". formatRating
joins formatCompactNumber in utils and keeps the one decimal.

The tests hard-coded '41M' and '1.2K', which is not a theoretical problem:
under de_DE two of the three failed, and under fr_FR all of them, because
compact notation is locale-dependent ('41 Mio.', '1,2 k'). Expected strings now
come from the same formatters, normalized the way testing-library normalizes
DOM text - some locales put a non-breaking space inside the number, so the raw
formatter output would not compare equal. Verified green under en_US, de_DE,
fr_FR, ja_JP and tr_TR.

Dropped the test that claimed to keep the download count whole: it only
asserted the text was in the DOM, and jsdom applies no layout, so it passed
with or without the fix. What survives covers the footer's rendering rules, and
says so rather than implying it covers the overflow.

Extracted CardFooterRating, one star and a slot for the score, so the card and
the skeleton stop repeating the cell and the skeleton can put a placeholder bar
where the score will land.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netomi
netomi requested a review from gnugomez September 8, 2026 11:25
@netomi
netomi merged commit c7e5ae2 into main Sep 8, 2026
5 checks passed
@netomi
netomi deleted the fix/card-footer-overflow branch September 8, 2026 11:27
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.

3 participants