Skip to content

perf(login): static shell gradient — fix general dashboard login jank#217

Merged
ahmetabdullahgultekin merged 1 commit into
mainfrom
fix/face-capture-fps-2026-06-12
Jun 12, 2026
Merged

perf(login): static shell gradient — fix general dashboard login jank#217
ahmetabdullahgultekin merged 1 commit into
mainfrom
fix/face-capture-fps-2026-06-12

Conversation

@ahmetabdullahgultekin

Copy link
Copy Markdown
Contributor

Problem

app.fivucsas dashboard login felt laggy on every screen (identifier / password / MFA / face), while verify.fivucsas stayed smooth — even with browser hardware-acceleration off on both. So it was not the face pipeline and not WebGPU (both surfaces share the same WASM/MediaPipe path).

Root cause (code-confirmed by comparing the two shells)

The dashboard auth shell ran continuous decorative motion that composited on the main thread:

  • gradientShift — brand gradient at background-size: 400% 400% with background-position animated infinitely → animating background-position can't be GPU-composited → full-viewport repaint every frame, on every login screen (the dominant cost).
  • FloatingShape orbs, each an infinite framer-motion animation with a per-frame backdrop-filter: blur(10px) re-composite.
  • glass card backdrop-filter: blur(20px) re-blurring the moving gradient each frame.

verify-app/HostedLoginApp.tsx uses a static radial gradient with no continuous animation — exactly why it is smooth.

Fix (matches verify; same colours/layout; fully reversible)

  • Shell gradient is static for everyone (no gradientShift pan) via shared loginShellBackgroundSx().
  • FloatingShapeone-shot fade/scale-in + soft radial fill (no infinite repeat, no animated backdrop-blur) → decoration with zero per-frame cost after mount.
  • Glass card blur kept on the now-static off-camera screens; dropped during the live FACE/PUZZLE camera step and under prefers-reduced-motion.
  • Honour prefers-reduced-motion (no orbs, flat card) as an extra a11y layer.

Net: dashboard login has no continuous compositing → renders as smoothly as verify.

Verification

  • tsc --noEmit ✅ · eslint (changed files) ✅ · 380/380 auth vitest ✅ · vite build
  • Real-product check on app.fivucsas after deploy (follow-up in PR thread).

Notes

The same gradientShift + FloatingShape anti-pattern is duplicated inline in 7 other auth pages (register / verify-email / reset / onboarding / accept-invite / forgot-password / secondary-auth). This PR fixes the login hot path; a DRY consolidation of the others is captured as a Phase-3 cleanup follow-up.

The app.fivucsas dashboard login felt laggy across EVERY login screen
(identifier / password / MFA / face), while verify.fivucsas stayed smooth —
even with browser hardware-acceleration off on both. Root cause was the
dashboard auth shell's decorative motion, not the face pipeline and not WebGPU
(both surfaces share the same WASM/MediaPipe path):

- `gradientShift`: the brand gradient was painted at `background-size: 400% 400%`
  with `background-position` animated infinitely. Animating background-position
  cannot be GPU-composited; it forces a full-viewport repaint every frame, on
  the main thread when hardware-acceleration is off. This ran on all login
  screens — the dominant cost.
- 5x `FloatingShape` orbs each ran an infinite framer-motion animation with a
  per-frame `backdrop-filter: blur(10px)` re-composite.
- the glass card `backdrop-filter: blur(20px)` re-blurred the moving gradient
  every frame.

verify.fivucsas (HostedLoginApp) uses a STATIC radial gradient with no
continuous animation — which is exactly why it is smooth.

Fix (matches verify; same colours/layout; reversible):
- shell gradient is now STATIC for everyone (no `gradientShift` pan) via the
  shared `loginShellBackgroundSx()`.
- `FloatingShape` orbs become a ONE-SHOT fade/scale-in with a soft radial fill
  (no infinite repeat, no animated backdrop-blur) — decoration with zero
  per-frame cost after mount.
- glass card blur kept on the (now static) off-camera screens; dropped during
  the live FACE/PUZZLE camera step and under prefers-reduced-motion.
- honour prefers-reduced-motion (no orbs, flat card) as an extra layer.

After this the dashboard login has no continuous compositing, so it renders as
smoothly as verify.fivucsas. tsc + eslint + 380 auth tests + vite build green.
@ahmetabdullahgultekin ahmetabdullahgultekin merged commit c8c017d into main Jun 12, 2026
4 checks passed
@ahmetabdullahgultekin ahmetabdullahgultekin deleted the fix/face-capture-fps-2026-06-12 branch June 12, 2026 10:08
ahmetabdullahgultekin added a commit that referenced this pull request Jun 12, 2026
…ges (#218)

The 7 standalone auth shells (Register, SecondaryAuthFlow, VerifyEmail,
ResetPassword, Onboarding, AcceptInvite, ForgotPassword) each carried a
byte-identical copy of the login-page jank anti-pattern that PR #217
already removed from LoginPage:

- an infinite `gradientShift` keyframe animation over `backgroundSize:
  400% 400%`, which animates `background-position` and so forces a
  full-viewport REPAINT every frame (main-thread when HW-accel is off); and
- decorative `FloatingShape` orbs that ran an INFINITE framer-motion loop
  with a per-frame `backdrop-filter: blur(10px)`.

Fix (presentational/perf only, behaviour-preserving):

- Replace every inline animated-gradient `sx` block with the shared
  `loginShellBackgroundSx()` (static brand gradient, same stops) from
  loginBackground.ts. The `@keyframes gradientShift` are deleted.
- Extract ONE shared decorative-orb component,
  `features/auth/components/FloatingShape.tsx` — the cheap ONE-SHOT
  fade/scale-in with a soft radial fill and no animated backdrop-blur (the
  target version LoginPage already shipped). LoginPage and all 7 pages now
  import it and their local inline `FloatingShape` definitions are removed
  (8 duplicate copies -> 1).
- Gate the orbs behind `!usePrefersReducedMotion()` on every page that
  renders them, matching LoginPage.

Each page keeps its exact colours, layout, glass-card `blur(20px)`, and
orb positions/sizes/delays. Orb counts are preserved (5 on most;
VerifyEmail keeps its 4; SecondaryAuthFlow renders none and only had an
unused FloatingShape def + the animated gradient, both removed).

Net -196 LOC across the 8 files plus the one shared component.

Verified: tsc --noEmit clean, eslint clean on all changed files, vitest
src/features/auth + src/pages 395/395 green, vite build OK.
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.

1 participant