Skip to content

feat: UI elevation -- accessibility, scroll/load performance, motion polish, token consistency#185

Merged
Sagargupta16 merged 6 commits into
mainfrom
feat/ui-elevation
Jun 28, 2026
Merged

feat: UI elevation -- accessibility, scroll/load performance, motion polish, token consistency#185
Sagargupta16 merged 6 commits into
mainfrom
feat/ui-elevation

Conversation

@Sagargupta16

Copy link
Copy Markdown
Owner

What

A refinement pass across the whole site: accessibility, scroll/load performance, motion polish, design-token consistency, and several real bug fixes. No new dependencies, no content or UI removed, motion kept visible.

The work was driven by a parallel multi-dimension audit + adversarial verification, then a DevTools performance trace to find the actual scroll-lag root cause (not guesses).

Why the site lagged on fast scroll

A trace under CPU throttle showed 50 simultaneous backdrop-filter blur layers and a long forced-reflow window during scroll. backdrop-filter only caches while its backdrop is static, but the backdrop here (aurora blobs + 3D canvas) animates every frame -- so blurs recomputed continuously. The worst offenders were 5 full-viewport-width .section-darker bands re-blurring the moving background.

Changes

Performance (scroll)

  • Replaced the 5 full-width .section-darker backdrop-blur bands with gradient overlays -- the dominant fast-scroll repaint. Verified gone in the built CSS.
  • AuroraBlobs animate transform (GPU) instead of left/top (per-frame layout).
  • 3D scene pauses during active scroll (resumes at rest) and is gated to desktop.
  • NavBar no longer transitions its blur radius; glass blur 12->10px.
  • Removed the cursor-following conic-gradient card border (heaviest per-frame paint, also calmer).
  • Lenis tuned to lerp-based smoothing so fast flicks stay responsive; all in-page scroll routed through Lenis; overscroll-behavior added.

Performance (load)

  • Credly badges request /size/220x220 thumbnails: ~43KB -> 25KB each across 20 badges, sharper on retina. Render-time helper, survives the weekly sync.

Accessibility (WCAG 2.2)

  • Skip-to-content link + main landmark; nav aria-label/aria-current/aria-expanded/aria-controls.
  • MobileMenu is now a real dialog: focus trap, Escape, body scroll-lock, focus return.
  • Contact form: aria-invalid + inline role="alert" error; success announced to screen readers.
  • Modal titles h3->h2; focus-trap edge fix; bare-key shortcut guard.
  • TEXT_MUTED bumped to clear AA contrast on the dark glass.

Bug fixes

  • AnimatedCounter: cancel rAF on unmount, render decimals (CGPA), drop redundant ref.
  • ParticleField: regenerate positions on count change (buffer desync).
  • InteractiveConstellation: cancel rAF before restart (visibilitychange loop stacking).
  • Contact form: preserve sender name on the success screen; surface non-200 send responses.
  • parseDate month/year guards; stable list keys.

Design system

  • Routed raw hex/rgba/easing literals through theme.ts tokens + --ch-* channels across the tree; wired MAX_WIDTH*/type tokens into sections; removed dead BLUE token.

Testing

  • pnpm type-check, pnpm lint (0 warnings), pnpm test (4/4), pnpm build -- all green locally.
  • Verified in-browser (Chrome DevTools): 0 console errors, MobileMenu dialog behavior (focus trap + Escape + scroll-lock + focus return), skip link, resized badge URLs, and that .section-darker ships as a gradient with no backdrop-filter.

Caveat: a clean before/after FPS number wasn't reproducible on the dev box (identical runs swung 24->51 fps; scripted scroll fights Lenis). What's deterministically proven is that the measured root causes are removed from the shipped build. Best validated with a real wheel-scroll.

Notes

  • Pre-existing Dependabot alerts on main are unrelated to this PR (no deps added/changed).

- AnimatedCounter: cancel rAF on unmount, support decimals (CGPA), drop redundant one-shot ref
- ParticleField: regenerate positions on count change (useMemo) to avoid buffer desync
- InteractiveConstellation: cancel rAF before restart so visibilitychange can't stack loops
- parseDate: guard unknown month (?? not ||) and non-finite year
- experienceHelpers: stable list keys for repeated bullet/skill strings
- AuroraBlobs: animate transform (x/y) instead of left/top so the blurred
  background layer composites on the GPU instead of forcing per-frame layout
- SceneBackground: pause the 3D frameloop during active scroll (resume at rest)
  via Lenis velocity; keeps motion visible where it reads
- ShootingStars: fewer streaks on mobile (viewport-gated count)
- CertBadge: request Credly /size/220x220 thumbnails (43KB->25KB each across
  20 badges, sharper on retina) via render-time helper that survives the sync
Replace hardcoded color/easing literals with the existing exports in
src/constants/theme.ts (TEXT_*, CYAN/PURPLE/GREEN/AMBER, GLASS_*, EASING.cinematic)
and --ch-* CSS channels across leaf section/card components. Byte-identical at
runtime; removes the per-component drift the token system was meant to prevent.
…ements

Accessibility (WCAG 2.2):
- skip-to-content link + main landmark; nav aria-label/current/expanded/controls
- MobileMenu is now a real dialog: focus trap, Escape, body scroll-lock, focus return
- focus-trap edge fix; contact form aria-invalid + inline error; success announced
- modal titles h3->h2; bare-key shortcut guard; spinner label dedup

State/UX correctness:
- contact: preserve sender name for the success screen, surface non-200 send errors,
  keep error toast until dismissed; GitHub calendar timeout fallback + link

Mobile/responsive:
- 44px touch targets, single breakpoint source, responsive menu width
- viewport-gated 3D scene (desktop only) and background layer counts

Motion/perf:
- once:true entrance reveals, press feedback, tabular-nums counters
- replace .section-darker backdrop-blur with gradient (kills the dominant
  fast-scroll repaint); NavBar no longer transitions blur radius; glass blur 12->10px
- remove cursor-following conic-gradient card border (calmer + cheaper per-frame paint)
- Lenis tuned (lerp) for responsive fast scroll; all scroll buttons routed through Lenis

Design system:
- wire MAX_WIDTH/token scales into sections; SectionHeader/GlassCard/modals/Toast
  through tokens; TEXT_MUTED bumped for AA contrast; delete dead BLUE token
Document the accessibility, scroll/load performance, motion, and design-token
refinements from this release.
Comment thread src/utils/credlyThumb.ts Fixed
CodeQL js/incomplete-url-substring-sanitization (high): url.includes("images.credly.com")
would match hostile URLs (images.credly.com.evil.com, ...?images.credly.com). Parse with
new URL() and compare hostname exactly.
@Sagargupta16 Sagargupta16 merged commit 3822c70 into main Jun 28, 2026
8 checks passed
@Sagargupta16 Sagargupta16 deleted the feat/ui-elevation branch June 28, 2026 09:09
@sonarqubecloud

Copy link
Copy Markdown

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.

2 participants