-
Notifications
You must be signed in to change notification settings - Fork 95
Use inject/provide to define popover/dropdown container #3308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ae1f53f to
0494c36
Compare
|
@vinicius73 Could you please explain why changing the default container from |
|
@raimund-schluessler this problem appears when we have more than one instance of In The solution was moving the container of If the We've faced the same problem in The viewer app already handles part of this problem Catching the sidebar event, and update its focus trap instance. So, using a common container solve the problem without hard changes in next-cloud components. This PR does not change any actual behavior of In some cases, we have a lot of This change makes the app developers able to handle this problem (if necessary) without hard changes, until we work in a more robust solution (a singleton instance of `focus trap focus-trap/focus-trap#428) I've already prepared a PR for server diff --git a/apps/files_sharing/src/views/SharingTab.provider.js b/apps/files_sharing/src/views/SharingTab.provider.js
new file mode 100644
index 00000000000..38fe212e57b
--- /dev/null
+++ b/apps/files_sharing/src/views/SharingTab.provider.js
@@ -0,0 +1,12 @@
+export const SHARING_TAB_ID = Symbol('menu::id')
+
+export const useSharingTabIDMixin = {
+ inject: {
+ $sharingTabID: { from: SHARING_TAB_ID, default: null },
+ },
+ computed: {
+ sharingTabIDSelector() {
+ return `#${this.$sharingTabID}`
+ },
+ },
+}
diff --git a/apps/files_sharing/src/views/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue
index d1416a6c0d1..a5eea691ee4 100644
--- a/apps/files_sharing/src/views/SharingTab.vue
+++ b/apps/files_sharing/src/views/SharingTab.vue
@@ -21,7 +21,7 @@
-->
<template>
- <div :class="{ 'icon-loading': loading }">
+ <div :id="randomID" :class="{ 'icon-loading': loading }">
<!-- error message -->
<div v-if="error" class="emptycontent" :class="{ emptyContentWithSections: sections.length > 0 }">
<div class="icon icon-error" />
@@ -89,6 +89,7 @@
import { CollectionList } from 'nextcloud-vue-collections'
import { generateOcsUrl } from '@nextcloud/router'
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar'
+import { NC_KEY_POPOVER_CONTAINER } from '@nextcloud/vue/dist/providers.js'
import axios from '@nextcloud/axios'
import { loadState } from '@nextcloud/initial-state'
@@ -120,8 +121,16 @@ export default {
mixins: [ShareTypes],
+ provide() {
+ return {
+ [NC_KEY_POPOVER_CONTAINER]: `#${this.randomID}`
+ }
+ },
+
data() {
return {
+ randomID: `SharingTab-${(Math.ceil((Math.random() * 900000) + 100)).toString(16)}`,
+
config: new Config(),
error: '',
|
|
I see, but I am still a bit puzzled, since they had a common container already, it was just not a provided div, but simply Edit: I guess, I don't understand the solution completely yet 🙈 |
My understanding is that if you have two focus traps sitting next to each other (for example as siblings) in the DOM they will compete for the focus. The focus can only be in one of the traps. If dropdown menus are attached to the body they are outside of any possible other focus trap (in particular the modal) and we have the competing situation. Attaching them to an element inside the current focus trap will make sure the focus can be in both traps at the same time. So the problem could be solved by changing the container of all popovers inside a modal. However this can be tedious if there are multiple menus. This commit allows changing the default container for all popovers in the modal at once. |
|
Ah, ok, I think now I got it. Thanks. I somehow was under the impression that it's about multiple So this PR just adds a convenience function for an app-specific solution that would be possible already (e.g. by touching every That's fine with me. But since it still requires devs to adjust their code, a note about this in the documentation for every component using the focus-trap (i.e. |
it helps to define the container of all popovers in the component tree at the same time Signed-off-by: Vinicius Reis <[email protected]>
0494c36 to
d10247b
Compare
Signed-off-by: Vinicius Reis <[email protected]>
ChristophWurst
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 🐘
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I think this whole approach is far too messy and complex. Maintaining this in the long run will be too cumbersome.
If multiple traps are fighting between each others, we should fix the issue at the root cause.
Here is my suggestion:
- We create a service that handle all the registered focus traps
- When a new focus trap is registered and activated, it pauses all the others. Example given:
- You open a Settings modal (like talk or mail)
- You open an Actions menu inside this modal
- Those two items will have thei rown focus traps
- The one that should have the priority should be the last activated, as they are (presumably) always initiated by a user action
- When the Actions menu gets closed, the previous trap can resume its activity
- This should maybe require us to create a
@nextcloud/focus-trap, where the first to register one initialize the manager.
Storing all data inwindow._nc_focus_trap_serviceor something. The same way we do with the event bus. This is how we properly share a service across various independent services/apps.
It helps to define the container of all popovers in the component tree at the same time.
Solving part of