Skip to content

perf(auth): static gradient + shared one-shot orbs across all auth pages#218

Merged
ahmetabdullahgultekin merged 1 commit into
mainfrom
perf/auth-pages-static-gradient-2026-06-12
Jun 12, 2026
Merged

perf(auth): static gradient + shared one-shot orbs across all auth pages#218
ahmetabdullahgultekin merged 1 commit into
mainfrom
perf/auth-pages-static-gradient-2026-06-12

Conversation

@ahmetabdullahgultekin

Copy link
Copy Markdown
Contributor

What & why

PR #217 (c8c017d) removed the login-page jank anti-pattern from LoginPage. The 7 other auth shells each carried a byte-identical copy of it, so the same jank persists on register / MFA / verify-email / reset / onboarding / accept-invite / forgot-password. This PR fixes all 7 and eliminates the resulting DRY violation.

The anti-pattern (per page)

  1. The brand gradient was painted with an infinite gradientShift keyframe over backgroundSize: '400% 400%'. Animating background-position cannot be GPU-composited → a full-viewport repaint every frame (on the main thread when hardware-acceleration is off).
  2. Decorative FloatingShape orbs each ran an INFINITE framer-motion loop with a per-frame backdrop-filter: blur(10px) — continuous main-thread compositing cost.

The fix (presentational / perf only — behaviour-preserving)

  • Replace every inline animated-gradient sx block with the shared loginShellBackgroundSx() (static brand gradient, identical stops) from loginBackground.ts; the dead @keyframes gradientShift are removed.
  • DRY extraction: new shared component src/features/auth/components/FloatingShape.tsx — the cheap one-shot fade/scale-in (opacity 0→0.28, scale 0.8→1, duration 1.2, ease easeOut) with a soft radial fill and no animated backdrop-blur (exactly the version LoginPage already shipped in perf(login): static shell gradient — fix general dashboard login jank #217). LoginPage and all 7 pages now import it; their local inline FloatingShape definitions are deleted (8 duplicate copies → 1).
  • Orbs are gated behind !usePrefersReducedMotion() on every page that renders them, matching LoginPage.

Each page keeps its exact colours, layout, glass-card backdrop-filter: blur(20px) (cheap over a now-static gradient; none of these pages has a live camera step), and orb positions/sizes/delays.

Reversibility

Pure presentational change. The static-gradient builder lives in loginBackground.ts (restore the gradientShift animation there to revert); the orb component is a single file.

Orb counts preserved (proof)

Page Orbs
LoginPage (re-uses shared component, output unchanged) 5
RegisterPage 5
SecondaryAuthFlow 0 (had an unused local FloatingShape def + the animated gradient — both removed; renders no orbs)
VerifyEmailPage 4
ResetPasswordPage 5
OnboardingPage 5
AcceptInvitePage 5
ForgotPasswordPage 5

Files changed

  • new src/features/auth/components/FloatingShape.tsx (shared one-shot orb)
  • src/features/auth/components/LoginPage.tsx (migrated to shared orb; output identical)
  • src/features/auth/components/RegisterPage.tsx
  • src/features/auth/components/SecondaryAuthFlow.tsx
  • src/pages/VerifyEmailPage.tsx
  • src/pages/ResetPasswordPage.tsx
  • src/pages/OnboardingPage.tsx
  • src/pages/AcceptInvitePage.tsx
  • src/pages/ForgotPasswordPage.tsx

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

Verification

Check Result
npx tsc --noEmit ✅ exit 0, no errors
npx eslint <9 changed files> ✅ exit 0, no warnings
npx vitest run src/features/auth src/pages 395/395 tests in 52 files
npx vite build ✅ exit 0 (pre-existing chunk-size + onnxruntime eval warnings only)

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.
@ahmetabdullahgultekin ahmetabdullahgultekin merged commit fb06132 into main Jun 12, 2026
4 checks passed
@ahmetabdullahgultekin ahmetabdullahgultekin deleted the perf/auth-pages-static-gradient-2026-06-12 branch June 12, 2026 10:23
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