Skip to content

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

Merged
susnux merged 3 commits intonextcloud-libraries:mainfrom
nikhil2297:fix/modal-focus-trap-race-condition
Apr 21, 2026
Merged

fix(NcModal): prevent focus trap race condition #8093
susnux merged 3 commits intonextcloud-libraries:mainfrom
nikhil2297:fix/modal-focus-trap-race-condition

Conversation

@nikhil2297
Copy link
Copy Markdown
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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown

codecov Bot commented Jan 19, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 54.41%. Comparing base (e00f649) to head (96de871).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/components/NcModal/NcModal.vue 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8093      +/-   ##
==========================================
- Coverage   54.57%   54.41%   -0.17%     
==========================================
  Files         104      104              
  Lines        3399     3398       -1     
  Branches      992      992              
==========================================
- Hits         1855     1849       -6     
- Misses       1305     1309       +4     
- Partials      239      240       +1     

☔ 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
Copy Markdown
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 2 times, most recently 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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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

Comment thread tests/component/components/NcModal.spec.ts Outdated
Comment thread src/components/NcModal/NcModal.vue Outdated
@nikhil2297
Copy link
Copy Markdown
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
Comment thread src/components/NcModal/NcModal.vue Outdated
@Sector6759
Copy link
Copy Markdown
Contributor

Would this fix #7946?

@susnux susnux force-pushed the fix/modal-focus-trap-race-condition branch from 75f40ee to db5c2de Compare April 20, 2026 20:04
nikhil2297 and others added 3 commits April 20, 2026 22:05
Signed-off-by: nikhil2297 <nikhillohar2297@gmail.com>
…available

Signed-off-by: nikhil2297 <nikhillohar2297@gmail.com>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
@susnux susnux force-pushed the fix/modal-focus-trap-race-condition branch from db5c2de to 96de871 Compare April 20, 2026 20:05
@susnux
Copy link
Copy Markdown
Contributor

susnux commented Apr 20, 2026

For @ShGKme I pushed one commit that solves the review comment.
Meaning focus trap is managed by the transition events, no need to custom safe guards or lifecycle events.
Except for unmounting, we need to enforce its removed on unmount.

@susnux susnux merged commit 93b7eaf into nextcloud-libraries:main Apr 21, 2026
22 of 24 checks passed
@susnux
Copy link
Copy Markdown
Contributor

susnux commented Apr 21, 2026

/backport to stable8

@backportbot
Copy link
Copy Markdown

backportbot Bot commented Apr 21, 2026

The backport to stable8 failed. Please do this backport manually.

# Switch to the target branch and update it
git checkout stable8
git pull origin stable8

# Create the new backport branch
git checkout -b backport/8093/stable8

# Cherry pick the change from the commit sha1 of the change against the default branch
# This might cause conflicts, resolve them
git cherry-pick 82881d9e d9e5508f 96de8716

# Push the cherry pick commit to the remote repository and open a pull request
git push origin backport/8093/stable8

Error: Failed to check for changes with origin/stable8: No changes found in backport branch


Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.

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 backport-request 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