Skip to content

Conversation

@sammy200-ui
Copy link
Contributor

@sammy200-ui sammy200-ui commented Dec 14, 2025

  • Added overflow hidden to body when modal opens to lock background scroll
  • Added cleanup function to restore scroll when modal closes
  • Fixes scroll chaining issue where background scrolls after reaching modal bottom

Fixes #4684

Summary by CodeRabbit

  • Bug Fixes
    • Modal windows now prevent page scrolling when opened, improving usability and preventing accidental interactions with background content.

✏️ Tip: You can customize this high-level summary in your review settings.

- Added overflow hidden to body when modal opens to lock background scroll
- Added cleanup function to restore scroll when modal closes
- Fixes scroll chaining issue where background scrolls after reaching modal bottom

Fixes asyncapi#4684
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

The Modal component now prevents background page scrolling when mounted by setting document.body.style.overflow to 'hidden' and restoring it during cleanup. This addresses scroll chaining behavior where scrolling within a modal continued to scroll the background page content.

Changes

Cohort / File(s) Summary
Modal scroll containment
components/Modal.tsx
Adds document body overflow control in modal mount/cleanup lifecycle to lock background scroll while modal is open

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

  • Single file with a straightforward side effect addition
  • Simple property manipulation with standard cleanup pattern
  • No complex logic or structural changes

Poem

🐰 A modal appears, the scroll must stay still,
Background locked down with overflow's will,
No chaining scrolls through the modal's great height,
Focus contained—the user's delight! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preventing background scroll when the roadmap modal is open, which directly addresses the core fix implemented in the PR.
Linked Issues check ✅ Passed The code changes directly address issue #4684 by implementing scroll locking on the document body during modal mount and restoring it on cleanup, which prevents scroll chaining and keeps background page non-scrollable while modal is open.
Out of Scope Changes check ✅ Passed All changes in Modal.tsx are scoped to addressing the scroll chaining issue by adding overflow management; no unrelated or out-of-scope modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@netlify
Copy link

netlify bot commented Dec 14, 2025

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit d96de74
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/693e8b13a7be510008dfe459
😎 Deploy Preview https://deploy-preview-4710--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link

codecov bot commented Dec 14, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (9c3dcd6) to head (d96de74).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #4710   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines          799       799           
  Branches       146       146           
=========================================
  Hits           799       799           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses issue #4684 by preventing background scroll when the roadmap modal is open. The implementation adds an overflow lock to the document body when the Modal component mounts and restores it on unmount using React's useEffect cleanup function.

Key Changes:

  • Added document.body.style.overflow = 'hidden' in the Modal component's useEffect to lock background scroll when modal opens
  • Added cleanup function to restore scroll by setting document.body.style.overflow = '' when modal closes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +23 to +27
document.body.style.overflow = 'hidden';

// Cleanup: restore scroll when modal is closed
return () => {
document.body.style.overflow = '';
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

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

The current implementation doesn't handle the case where multiple Modal instances might be mounted simultaneously. If two modals are open and the first one closes, it will restore body scroll even though the second modal is still open. Consider implementing a reference counting mechanism or using a shared state manager to track the number of open modals, and only restore overflow when the count reaches zero.

Suggested change
document.body.style.overflow = 'hidden';
// Cleanup: restore scroll when modal is closed
return () => {
document.body.style.overflow = '';
openModalCount += 1;
if (openModalCount === 1) {
document.body.style.overflow = 'hidden';
}
// Cleanup: restore scroll when modal is closed
return () => {
openModalCount -= 1;
if (openModalCount === 0) {
document.body.style.overflow = '';
}

Copilot uses AI. Check for mistakes.
@asyncapi-bot
Copy link
Contributor

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 38
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-4710--asyncapi-website.netlify.app/

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c3dcd6 and d96de74.

📒 Files selected for processing (1)
  • components/Modal.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Redirect rules - asyncapi-website
  • GitHub Check: Header rules - asyncapi-website
  • GitHub Check: Pages changed - asyncapi-website
  • GitHub Check: cypress-run
  • GitHub Check: Lighthouse CI
  • GitHub Check: Test NodeJS PR - windows-latest

Comment on lines +18 to 29
// Focus the modal when it mounts and lock body scroll
useEffect(() => {
if (modalRef.current) modalRef.current.focus();

// Prevent background scroll when modal is open
document.body.style.overflow = 'hidden';

// Cleanup: restore scroll when modal is closed
return () => {
document.body.style.overflow = '';
};
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, examine the Modal component file structure
find . -type f -name "Modal.tsx" | head -5

Repository: asyncapi/website

Length of output: 82


🏁 Script executed:

# Check for all references to body.style.overflow in the codebase
rg "body\.style\.overflow|document\.body\.style\.overflow" --type tsx --type ts -n

Repository: asyncapi/website

Length of output: 87


🏁 Script executed:

# Search for Modal usage patterns to understand stacking scenarios
rg "Modal|<Modal" --type tsx --type ts -B 2 -A 2 | head -100

Repository: asyncapi/website

Length of output: 87


🏁 Script executed:

# Check for overscroll-behavior in CSS or Tailwind configs
rg "overscroll|scroll-contain" --type css --type tsx -n

Repository: asyncapi/website

Length of output: 87


🏁 Script executed:

# Look at the complete Modal component to understand context
cat -n components/Modal.tsx 2>/dev/null || find . -path "*/components/Modal.tsx" -exec cat -n {} \;

Repository: asyncapi/website

Length of output: 3256


🏁 Script executed:

# Search for Modal imports and usage
grep -r "Modal" --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" | grep -i "import\|<Modal" | head -20

Repository: asyncapi/website

Length of output: 326


🏁 Script executed:

# Search for body.style.overflow without file type restriction
grep -r "body\.style\.overflow\|document\.body\.style\.overflow" . 2>/dev/null | grep -v node_modules

Repository: asyncapi/website

Length of output: 191


🏁 Script executed:

# Check if there are multiple Modal instances rendered simultaneously anywhere
grep -r "<Modal" --include="*.tsx" --include="*.jsx" -B 5 -A 5 | head -60

Repository: asyncapi/website

Length of output: 721


🏁 Script executed:

# Look for any overflow manipulation in CSS or global styles
find . -name "*.css" -o -name "tailwind.config.*" | xargs grep -l "overflow\|overscroll" 2>/dev/null | head -10

Repository: asyncapi/website

Length of output: 101


🏁 Script executed:

# Check globals.css for any overflow or body styles
cat -n ./styles/globals.css | head -100

Repository: asyncapi/website

Length of output: 2501


🏁 Script executed:

# Check tailwind.config.ts for overscroll or scroll-related settings
cat -n ./tailwind.config.ts

Repository: asyncapi/website

Length of output: 7484


Restore previous body.style.overflow as defensive programming for potential modal stacking.

The current cleanup sets document.body.style.overflow = '', which could cause issues if (a) the modal component is reused in contexts where multiple modals stack, or (b) body.style.overflow is set elsewhere in the future. While the current codebase only renders a single Modal instance at a time (in RoadmapPill.tsx), storing and restoring the previous value follows best practices and prevents regressions:

 export default function Modal({ title, children, onModalClose = () => {} }: IModalProps) {
   const modalRef = useRef<HTMLDivElement>(null);
+  const prevBodyOverflowRef = useRef<string>('');
 
   // Focus the modal when it mounts and lock body scroll
   useEffect(() => {
     if (modalRef.current) modalRef.current.focus();
 
     // Prevent background scroll when modal is open
-    document.body.style.overflow = 'hidden';
+    prevBodyOverflowRef.current = document.body.style.overflow;
+    document.body.style.overflow = 'hidden';
 
     // Cleanup: restore scroll when modal is closed
     return () => {
-      document.body.style.overflow = '';
+      document.body.style.overflow = prevBodyOverflowRef.current;
     };
   }, []);

The optional overscroll-behavior: contain mitigation is not currently needed, as the modal uses fixed positioning and doesn't exhibit scroll chaining behavior.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In components/Modal.tsx around lines 18–29, the effect currently sets
document.body.style.overflow = 'hidden' and restores it to '' on cleanup; change
it to capture the previous document.body.style.overflow value before
overwriting, set overflow to 'hidden' on mount, and restore the saved previous
value on cleanup so stacked modals or external overflow modifications are
preserved (save value to a local variable outside the cleanup and assign it back
in the return function).

@sammy200-ui
Copy link
Contributor Author

@princerajpoot20 Modal is only used in RoadmapPill.tsxwith fixed inset-0 positioning
Only one modal can be open at a time - users must close the current modal before accessing another roadmap item
body.style.overflow is not set anywhere else in the codebase
Global CSS has no overflow property on the body element.
If multiple simultaneous modals or dynamic body overflow management become requirements in the future, that would warrant a more robust modal management system as a separate feature. For now, this fix addresses the specific bug without over-engineering.

the suggestion left by copilot and coderabbit is unnecessary for the current implementation.

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.

[BUG] Background page scrolls when reaching the end of Roadmap modal content

2 participants