Skip to content

fix(NcModal): prevent focus trap race condition #8093

Open
nikhil2297 wants to merge 4 commits intonextcloud-libraries:mainfrom
nikhil2297:fix/modal-focus-trap-race-condition
Open

fix(NcModal): prevent focus trap race condition #8093
nikhil2297 wants to merge 4 commits intonextcloud-libraries:mainfrom
nikhil2297:fix/modal-focus-trap-race-condition

Conversation

@nikhil2297
Copy link
Contributor

@nikhil2297 nikhil2297 commented Jan 17, 2026

☑️ Resolves

🖼️ Screenshots

🏚️ Before 🏡 After
Focus trap error: fallbackFocus was specified but was not a node occurring ~30% of the time during modal mounting Error prevented by null check - focus trap waits for DOM elements to be ready

🚧 Tasks

  • Add null check in useFocusTrap() to prevent race condition
  • Add test cases to verify the fix
  • Ensure existing functionality is preserved

🏁 Checklist

  • ⛑️ Tests are included or are not applicable
  • 📘 Component documentation has been extended, updated or is not applicable
  • 2️⃣ Backport to stable8 for maintained Vue 2 version or not applicable

Signed-off-by: nikhil2297 <nikhillohar2297@gmail.com>
Copy link
Contributor

@susnux susnux left a comment

Choose a reason for hiding this comment

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

Should we not also remove the onMounted(() => useFocusTrap()) ?

@susnux susnux requested review from Antreesy and ShGKme January 18, 2026 13:43
@nikhil2297
Copy link
Contributor Author

Should we not also remove the onMounted(() => useFocusTrap()) ?

I added a null check in useFocusTrap() which fixes the issue and the useFocusTrap() already has guards for edge cases, so there's no downside to keeping the onMounted() call.

@codecov
Copy link

codecov bot commented Jan 19, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 52.77%. Comparing base (7865f41) to head (36e72ac).

Files with missing lines Patch % Lines
src/components/NcModal/NcModal.vue 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8093      +/-   ##
==========================================
- Coverage   52.77%   52.77%   -0.01%     
==========================================
  Files         103      103              
  Lines        3348     3350       +2     
  Branches      976      978       +2     
==========================================
+ Hits         1767     1768       +1     
- Misses       1333     1334       +1     
  Partials      248      248              

☔ 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.

@susnux
Copy link
Contributor

susnux commented Jan 19, 2026

so there's no downside to keeping the onMounted() call.

Well its a useless function call as it will always fail 😉

But anyway: Can you please fix the failing linter?

@nikhil2297 nikhil2297 force-pushed the fix/modal-focus-trap-race-condition branch from 1410b80 to bfeeeab Compare January 19, 2026 18:47
Signed-off-by: nikhil2297 <nikhillohar2297@gmail.com>
@nikhil2297 nikhil2297 force-pushed the fix/modal-focus-trap-race-condition branch from bfeeeab to ba1d1d2 Compare January 19, 2026 18:51
@nikhil2297 nikhil2297 requested a review from susnux January 19, 2026 19:15
@nikhil2297
Copy link
Contributor Author

so there's no downside to keeping the onMounted() call.

Well its a useless function call as it will always fail 😉

But anyway: Can you please fix the failing linter?

Perfect, I've fixed the linter part and did the npm run lint test everything is good. But I'm skeptical about the new line which I have added at EOF but idk why I'm not able to see it in the github commit file changes.

Copy link
Contributor

@susnux susnux left a comment

Choose a reason for hiding this comment

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

Still think that the known-to-fail onMounted call should be removed but the fix itself seems to work fine!

Copy link
Contributor

@Antreesy Antreesy left a comment

Choose a reason for hiding this comment

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

Otherwise good. Although I'm also not seeing a point in keeping onMounted hook

…available

Signed-off-by: nikhil2297 <nikhillohar2297@gmail.com>
@nikhil2297
Copy link
Contributor Author

This change doesn’t skip focus trap initialization if maskElement isn’t available it defers it until the element is present.

Changes:

  • Removed the onMounted call.
  • Added a watcher to initialize the focus trap when maskElement becomes available
  • Kept the null check for maskElement to handle cases where NcModal is used with v-if

@nikhil2297 nikhil2297 requested a review from ShGKme January 21, 2026 21:29
@Sector6759
Copy link
Contributor

Would this fix #7946?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useFocusTrap: fallbackFocus was specified but was not a node, or did not return a node

5 participants