Skip to content

perf(store): fix packs tab stutter (animated drop-shadow filters + per-tile backdrop blur) - #4821

Merged
evanpelle merged 1 commit into
mainfrom
fix/store-packs-perf
Aug 1, 2026
Merged

perf(store): fix packs tab stutter (animated drop-shadow filters + per-tile backdrop blur)#4821
evanpelle merged 1 commit into
mainfrom
fix/store-packs-perf

Conversation

@evanpelle

Copy link
Copy Markdown
Collaborator

Problem

The store's packs tab on openfront.io is slow and stuttery, while local dev feels fine. Local dev has no API, so no packs render — the regression only appears when pack tiles are present.

Diagnosis

Reproduced production locally by intercepting cosmetics.json with the real prod catalog (7 plutonium packs) and measuring the store in a headless-Chromium harness:

Condition FPS Median frame
Packs tab as shipped 17.7 50ms (104/106 frames > 33ms)
Plutonium icon animations paused 60.0 16.7ms

Each plutonium-icon runs three infinite CSS animations, and any one of them alone tanks the tab to ~16fps:

  • plutonium-pulse animates filter: drop-shadow(...) (2–3 stacked shadows) — not compositor-animatable, re-rasterizes the icon every frame
  • plutonium-jiggle — a 0.15s infinite ±0.4px jitter, visually imperceptible but keeps the compositor permanently busy
  • plutonium-rotate — fine by itself in principle, but every animated frame re-renders a scene containing 867 elements with backdrop-filter: blur(8px) (every cosmetic tile + modal shell)

A devtools trace confirmed the main thread is nearly idle — the cost is all compositor/raster work, which is exactly what stutters iGPU/mid-range machines. plutonium-icon is also used in the header currency-display, so logged-in users paid this cost outside the packs grid too.

Fix

  • PlutoniumIcon: the pulse is now a pre-blurred radial-gradient glow layer animating only opacity/transform (compositor-only), with a static drop-shadow on the icon; the jiggle is removed; the 7s rotation stays. will-change hints added.
  • CosmeticContainer: drop the per-tile backdrop-filter: blur(8px). Tile backgrounds are ~85%-opaque gradients over the already-blurred modal shell, so the per-tile blur is visually invisible — but it multiplied blur surfaces 867 → 21.

Results

Same harness after the change: ~39fps with all animations running (up from 17.7), and the median frame reaches 16.7ms (60fps) once the modal-shell blur — trivial for real GPUs, slow only under the harness's software rasterizer — is excluded. Before/after screenshots are visually identical (glow pulse look preserved).

Caveat: absolute numbers come from software-rendered headless Chromium, which exaggerates raster cost; the eliminated work (per-frame filter rasterization × dozens of blur surfaces) is what matters on real hardware.

🤖 Generated with Claude Code

…er-tile backdrop blur

The store packs tab ran three infinite CSS animations per plutonium icon,
including one animating filter: drop-shadow (re-rasterized every frame) and
a 0.15s sub-pixel jiggle, over a grid where every cosmetic tile also had
backdrop-filter: blur(8px). Any one of these animations forced the whole
blurred scene to re-render each frame: with the production catalog the
packs tab measured ~18fps (median frame 50ms) in a software-rendered
harness, and 60fps with the icon animations paused.

- PlutoniumIcon: pulse now animates opacity/scale of a pre-blurred
  radial-gradient glow layer (compositor-only) with a static drop-shadow
  on the icon; the jiggle is removed; the 7s rotation stays.
- CosmeticContainer: drop the per-tile backdrop blur — tile backgrounds
  are ~85% opaque gradients over the already-blurred modal shell, so it
  was invisible but multiplied blur surfaces (867 -> 21).

Same harness after the change: ~39fps with all animations running, and a
16.7ms median frame once the modal-shell blur (GPU-trivial on real
hardware) is excluded. Visuals are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 921ab974-c355-492d-b818-adf5fa9b6bc7

📥 Commits

Reviewing files that changed from the base of the PR and between daec50e and 5f07744.

📒 Files selected for processing (2)
  • src/client/components/CosmeticContainer.ts
  • src/client/components/PlutoniumIcon.ts

Walkthrough

The changes remove an ineffective tile blur and update Plutonium icon animations. The icon now uses opacity, transforms, a radial-gradient glow, and a static image shadow.

Changes

Cosmetic rendering updates

Layer / File(s) Summary
Tile blur removal
src/client/components/CosmeticContainer.ts
The host tile no longer applies backdrop-filter: blur(8px).
Plutonium icon animation
src/client/components/PlutoniumIcon.ts
The icon uses compositor-friendly opacity and transform keyframes, a radial-gradient glow overlay, relative positioning, and a static drop shadow.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: celant, ryanbarlow97

Poem

Blur fades away,
Plutonium softly glows,
Transforms carry light,
Opacity pulses clean,
Shadows stay still and bright.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the store packs tab stutter and the two main performance fixes.
Description check ✅ Passed The description directly explains the stutter, diagnosis, implementation changes, and measured performance results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@evanpelle evanpelle added this to the v33 milestone Aug 1, 2026
@evanpelle
evanpelle merged commit d33a586 into main Aug 1, 2026
15 of 16 checks passed
@evanpelle
evanpelle deleted the fix/store-packs-perf branch August 1, 2026 23:28
@github-project-automation github-project-automation Bot moved this from Triage to Complete in OpenFront Release Management Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

1 participant