Skip to content

Add reusable MouseParallax component to Hero for layered visual depth - #160

Merged
krishkhinchi merged 1 commit into
7-Blocks:mainfrom
littlegod20:feat/reusable-mouse-parallax-component
Aug 2, 2026
Merged

Add reusable MouseParallax component to Hero for layered visual depth#160
krishkhinchi merged 1 commit into
7-Blocks:mainfrom
littlegod20:feat/reusable-mouse-parallax-component

Conversation

@littlegod20

@littlegod20 littlegod20 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

  • Adds a reusable MouseParallax component that tracks cursor position relative to its container and applies spring-smoothed X/Y translation via Framer Motion.
  • Supports configurable strength, className, and spring physics (stiffness, damping, mass) so layers can move at different depths.
  • Integrates layered parallax into the Hero section: particles (strength={20}), orbit satellites (strength={10}), and globe (strength={20}) for a more immersive orbital feel.
  • Resets motion to center on mouse leave for a clean idle state.

Related Issue

#152

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation update
  • 🚀 Performance improvement
  • 🎨 UI/UX enhancement
  • 🔧 Refactoring
  • 🧹 Chore / Maintenance
  • 🔒 Security improvement

Screenshots / Screen Recordings

mouse_parallax.mp4

Testing Performed

  • Tested locally
  • Tested relevant functionality
  • Checked for linting errors
  • Checked for TypeScript/build errors
  • Tested responsive behavior (if applicable)

Verified that Hero layers follow the cursor with spring easing, different strengths produce distinct depth, and motion resets when the pointer leaves the parallax region.

Breaking Changes

None.

Checklist

  • I have read and followed the contributing guidelines.
  • My code follows the project's coding standards and guidelines.
  • I have completed testing of my changes.
  • I have updated documentation where applicable.
  • I have checked that my changes do not introduce unintended regressions.

ECSoC26 Submission

ECSoC26 contributors only — select your difficulty level by checking exactly one box below.
Leaving all boxes unchecked, or checking more than one, will cause the automation to fail.

  • ECSoC26-L1 – Beginner
  • ECSoC26-L2 – Intermediate
  • ECSoC26-L3 – Advanced

CodeAnt-AI Description

Add cursor-driven layered motion to the Hero visual

What Changed

  • Hero background particles, satellites, and globe now shift in response to the cursor
  • Each visual layer moves at a different strength to create a depth effect
  • Motion eases smoothly and returns to the centered position when the cursor leaves
  • The cursor motion behavior is reusable for other visual elements

Impact

✅ More immersive Hero visuals
✅ Clearer layered depth
✅ Smooth reset when leaving the Hero

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features

    • Added smooth mouse-responsive parallax effects to hero background elements, including particles, satellites, and the globe.
    • Added configurable motion behavior for interactive visual elements.
  • Enhancements

    • Background layers now move independently and reset smoothly when the pointer leaves the area.

@codeant-ai

codeant-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 03a19d4 Aug 01, 2026 · 22:04 22:06

@codeant-ai

codeant-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request frontend Frontend development size/M Medium-sized contribution. ECSoC26 Official label for ECSoC26 event contributions. size:M This PR changes 30-99 lines, ignoring generated files ECSoC26-L2 Level 2 contribution for the ECSoC26 event. type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:feature Introduces a new feature or enhancement. type:frontend Changes frontend or client-side code. labels Aug 1, 2026
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a reusable MouseParallax component. The Hero component applies separate parallax strengths to its particles, satellites, and globe.

Changes

Hero parallax interaction

Layer / File(s) Summary
MouseParallax component
frontend/src/components/MouseParallax.tsx
Adds configurable pointer-based translation with spring smoothing and mouse-leave reset behavior.
Hero background integration
frontend/src/components/Hero.tsx
Wraps the particles, satellites, and globe with MouseParallax using strengths of 20, 10, and 20.

Estimated code review effort: 3 (Moderate) | ~15 minutes

Possibly related issues

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Pointer
  participant Hero
  participant MouseParallax
  participant BackgroundLayers
  Pointer->>MouseParallax: provide pointer position
  Hero->>MouseParallax: render background layer
  MouseParallax->>BackgroundLayers: apply spring-smoothed translation
  Pointer->>MouseParallax: trigger mouse-leave reset
  MouseParallax->>BackgroundLayers: restore translation
Loading

Suggested reviewers: thelinuxguy-ssh

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly and concisely describes adding the reusable MouseParallax component and integrating it into Hero.
Description check ✅ Passed The description covers the summary, issue, change type, screenshot, testing, breaking changes, checklist, and required ECSoC26 level.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions github-actions Bot added the AI Artificial Intelligence and Machine Learning label Aug 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/Hero.tsx`:
- Around line 29-45: Update the Hero component’s pointer tracking so a single
shared Hero-level region provides motion values to Particles, OrbitSatellites,
and Globe, rather than nesting separate MouseParallax handlers on overlapping
layers. Pass the shared values to each layer and apply their existing strengths
independently, ensuring all layers respond even when visually overlapped.

In `@frontend/src/components/MouseParallax.tsx`:
- Around line 29-40: Update handleMouseMove to guard against zero rect.width or
rect.height before calculating offsets; when either dimension is zero, reset
both motion values via x and y and return, preserving the existing offset
calculations for non-zero containers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a3a50a0c-cbdd-4e32-9900-c3d6e910293c

📥 Commits

Reviewing files that changed from the base of the PR and between 6aa8247 and 03a19d4.

📒 Files selected for processing (2)
  • frontend/src/components/Hero.tsx
  • frontend/src/components/MouseParallax.tsx

Comment on lines +29 to +45
<MouseParallax className="absolute inset-0" strength={20}>
<Particles quantity={220} />
</MouseParallax>


<div
className="absolute left-1/2 top-[32%] h-[240px] w-[240px] max-w-[85vw] -translate-x-1/2 -translate-y-1/2 opacity-40
sm:left-auto sm:right-[3%] sm:top-1/2 sm:h-[380px] sm:w-[380px] sm:translate-x-0 sm:-translate-y-1/2 sm:opacity-70
lg:right-[5%] lg:h-[520px] lg:w-[520px] lg:opacity-90"
>
<OrbitSatellites />
<div className="absolute inset-0 flex items-center justify-center">
<MouseParallax strength={10}>
<OrbitSatellites />
</MouseParallax>

<MouseParallax strength={20} className="absolute inset-0 flex items-center justify-center">
<Globe className="h-max-[480px] w-max-[480px]" />
</div>
</MouseParallax>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Use one pointer-tracking region for all overlapping layers.

The absolute inset-0 globe wrapper at Line 43 covers the satellite wrapper at Lines 39-41. It receives the mouse events, so OrbitSatellites cannot update its own MouseParallax values. The particle layer has the same limitation where later hero content overlaps it.

Track the pointer on a common Hero region. Share the resulting motion values with each layer, then apply each layer strength independently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/Hero.tsx` around lines 29 - 45, Update the Hero
component’s pointer tracking so a single shared Hero-level region provides
motion values to Particles, OrbitSatellites, and Globe, rather than nesting
separate MouseParallax handlers on overlapping layers. Pass the shared values to
each layer and apply their existing strengths independently, ensuring all layers
respond even when visually overlapped.

Comment on lines +29 to +40
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
const rect = ref.current?.getBoundingClientRect();
if (!rect) return;

const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;

const offsetX = (e.clientX - centerX) / (rect.width / 2);
const offsetY = (e.clientY - centerY) / (rect.height / 2);

x.set(offsetX * strength);
y.set(offsetY * strength);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard zero-sized containers before calculating offsets.

rect.width or rect.height can be zero when children are absolutely positioned. The division then produces Infinity or NaN, which can leave the motion values in an invalid state. Reset the values and return when either dimension is zero.

Proposed fix
         const rect = ref.current?.getBoundingClientRect();
         if (!rect) return;
+        if (rect.width <= 0 || rect.height <= 0) {
+            x.set(0);
+            y.set(0);
+            return;
+        }

         const centerX = rect.left + rect.width / 2;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
const rect = ref.current?.getBoundingClientRect();
if (!rect) return;
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const offsetX = (e.clientX - centerX) / (rect.width / 2);
const offsetY = (e.clientY - centerY) / (rect.height / 2);
x.set(offsetX * strength);
y.set(offsetY * strength);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
const rect = ref.current?.getBoundingClientRect();
if (!rect) return;
if (rect.width <= 0 || rect.height <= 0) {
x.set(0);
y.set(0);
return;
}
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const offsetX = (e.clientX - centerX) / (rect.width / 2);
const offsetY = (e.clientY - centerY) / (rect.height / 2);
x.set(offsetX * strength);
y.set(offsetY * strength);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/MouseParallax.tsx` around lines 29 - 40, Update
handleMouseMove to guard against zero rect.width or rect.height before
calculating offsets; when either dimension is zero, reset both motion values via
x and y and return, preserving the existing offset calculations for non-zero
containers.

Comment on lines +29 to +31
<MouseParallax className="absolute inset-0" strength={20}>
<Particles quantity={220} />
</MouseParallax>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The new parallax effects are unconditionally enabled, including spring-driven transforms for users whose system requests reduced motion. The existing reduced-motion handling only affects CSS animations and cannot disable these Framer Motion updates, so the hero introduces pointer-driven motion despite that accessibility preference. [possible bug]

Severity Level: Major ⚠️
- ⚠️ Landing Hero still moves under reduced-motion preference.
- ⚠️ Particle, satellite, and globe layers remain spring-driven.
- ⚠️ Accessibility behavior differs from other heroes' motion handling.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/components/Hero.tsx
**Line:** 29:31
**Comment:**
	*Possible Bug: The new parallax effects are unconditionally enabled, including spring-driven transforms for users whose system requests reduced motion. The existing reduced-motion handling only affects CSS animations and cannot disable these Framer Motion updates, so the hero introduces pointer-driven motion despite that accessibility preference.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +39 to +41
<MouseParallax strength={10}>
<OrbitSatellites />
</MouseParallax>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The satellite parallax wrapper has no sizing or positioning class, while OrbitSatellites renders only absolutely positioned content. Consequently this wrapper collapses to zero height, so it does not receive pointer movement and the parallax effect never works for the satellites; if a mouse event is delivered, the component also divides by the zero height. [layout error]

Severity Level: Major ⚠️
- ❌ Satellite layer does not receive parallax interaction.
- ⚠️ Satellite Y translation can become invalid.
- ⚠️ Hero loses the advertised layered depth effect.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/components/Hero.tsx
**Line:** 39:41
**Comment:**
	*Layout Error: The satellite parallax wrapper has no sizing or positioning class, while `OrbitSatellites` renders only absolutely positioned content. Consequently this wrapper collapses to zero height, so it does not receive pointer movement and the parallax effect never works for the satellites; if a mouse event is delivered, the component also divides by the zero height.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@krishkhinchi krishkhinchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!

@krishkhinchi
krishkhinchi merged commit 262d3f5 into 7-Blocks:main Aug 2, 2026
13 checks passed
@ecsoc-sentinel ecsoc-sentinel Bot added ECSoC26-L2 Level 2 contribution for the ECSoC26 event. and removed ECSoC26-L2 Level 2 contribution for the ECSoC26 event. labels Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Artificial Intelligence and Machine Learning bug Something isn't working documentation Improvements or additions to documentation ECSoC26-L2 Level 2 contribution for the ECSoC26 event. ECSoC26 Official label for ECSoC26 event contributions. enhancement New feature or request frontend Frontend development size/M Medium-sized contribution. size:M This PR changes 30-99 lines, ignoring generated files type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:feature Introduces a new feature or enhancement. type:frontend Changes frontend or client-side code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants