- Splits About and Contact pages into separate chunks using React.lazy and Suspense.
- Keeps Home page eager loaded to prevent layout shifts.
- Adds PageLoader component as a fallback for Suspense.
- Reduces initial bundle size by loading secondary pages only when needed.
- Replaces the `cancelAnimationFrame` pattern with a boolean ticking flag to reduce function allocation and RAF overhead on high-frequency mousemove events.
- Uses closure variables for coordinates to ensure the latest position is used in the animation frame.
- Improves performance of the custom cursor on high-refresh-rate input devices.
Refactored the `Button` component to accept and spread standard HTML button attributes.
This allows developers to add `aria-label`, `aria-expanded`, and other accessibility properties,
which were previously ignored.
Added unit tests to verify that attributes are correctly passed to the DOM element.
Add `aria-invalid` and `aria-describedby` attributes to Input and Textarea components when an error is present.
This ensures screen readers announce the validation error when the input is focused.
Also added unit tests for these accessibility attributes.
* 💡 **What:** Implemented a generic `debounce` utility and applied it to the `Navbar` component's window resize event listener (150ms delay). Added a `.cancel()` method to the debounce utility to prevent memory leaks/errors on unmount.
* 🎯 **Why:** The `resize` event fires rapidly, causing `getBoundingClientRect` (a layout-thrashing operation) to run excessively, impacting performance.
* 📊 **Measured Improvement:** In a benchmark test simulating 100 rapid resize events:
* **Baseline:** 200 calls to `getBoundingClientRect`.
* **Optimized:** 2 calls to `getBoundingClientRect`.
* **Result:** ~99% reduction in layout calculations during rapid resizing.
* Added `src/components/layout/Navbar.perf.test.tsx` to prevent regression.
Added `sanitizeInput` utility to escape HTML characters.
Updated `Contact.tsx` to sanitize inputs before sending via `emailjs`.
Added max length validation for Name (100), Subject (200), and Message (5000).
Updated tests to cover sanitization and validation logic, including adding `cleanup()` to prevent test leakage.
- Removed synchronous `getBoundingClientRect` call from `pointermove` handler
- Implemented caching of canvas dimensions and scroll position using `ResizeObserver`
- Added logic to compensate for scroll delta in pointer position calculation
- Added regression test to verify `getBoundingClientRect` is not called during pointer interaction
- Fixed `ogl` mock in tests to include `Geometry`
- Replaced window scroll event listener with IntersectionObserver for better performance.
- Added a sentinel element to track scroll position relative to the top.
- Updated tests to mock IntersectionObserver and verify behavior without scroll events.
Removes the unconditional start of the animation loop on mount. The loop is now exclusively managed by the existing IntersectionObserver, ensuring it only runs when the component is visible.
Updates tests to reflect this behavior by simulating intersection events to trigger the animation.
Refactored the useTypingEffect hook to use a Ref for accessing the current text state inside the timer loop.
This prevents the main useEffect from being torn down and recreated on every single character keystroke, significantly reducing timer setup/cleanup overhead.
Baseline Effect Runs for 'Hello': 13
Optimized Effect Runs for 'Hello': 4
Also split the logic into two effects:
1. One for handling immediate state transitions (word switching).
2. One for the timer loop (typing/deleting/pausing).
This ensures correct behavior while maximizing performance.
Implemented `requestAnimationFrame` throttling for the scroll event listener in `Navbar` to reduce the frequency of state updates and logic execution.
- Wrapped scroll handler in `requestAnimationFrame`.
- Added performance test `src/components/layout/Navbar.test.tsx` verifying logic runs once per frame instead of per event.
- Verified functional correctness of scroll state updates.
- Fixed `useTypingEffect` test environment.
- Implements requestAnimationFrame throttling for the scroll event listener in Hero.tsx
- Adds cleanup for the animation frame on component unmount
- Adds unit tests to verify behavior and throttling logic
- Added IntersectionObserver to track component visibility.
- Paused requestAnimationFrame loop when component is not intersecting.
- Resumed loop when component becomes visible.
- Added unit tests to verify start/stop behavior.
Refactor useTypingEffect to use a single useEffect with proper cleanup for all timers, preventing state updates on unmounted components.
Add unit tests to verify behavior and ensure no memory leaks on unmount.