Skip to content

Commit c39a056

Browse files
authored
Merge pull request #4953 from nextcloud-libraries/fix/4910/nc-popover--integrate-with-current-focus-trap
fix(NcActions): intercept into current focus trap stack
2 parents 7665b6e + 6060690 commit c39a056

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/components/NcActions/NcActions.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ p {
813813
import NcButton from '../NcButton/index.js'
814814
import NcPopover from '../NcPopover/index.js'
815815
import GenRandomId from '../../utils/GenRandomId.js'
816+
import { getTrapStack } from '../../utils/focusTrap.js'
816817
import { t } from '../../l10n.js'
817818
818819
import Vue, { computed } from 'vue'
@@ -1009,6 +1010,7 @@ export default {
10091010
* @type {'menu'|'navigation'|'dialog'|'tooltip'|''}
10101011
*/
10111012
actionsMenuSemanticType: '',
1013+
externalFocusTrapStack: [],
10121014
}
10131015
},
10141016
@@ -1035,6 +1037,10 @@ export default {
10351037
10361038
this.opened = state
10371039
},
1040+
1041+
opened() {
1042+
this.intersectIntoCurrentFocusTrapStack()
1043+
},
10381044
},
10391045
10401046
methods: {
@@ -1048,6 +1054,33 @@ export default {
10481054
return action?.componentOptions?.Ctor?.extendOptions?.name ?? action?.componentOptions?.tag
10491055
},
10501056
1057+
/**
1058+
* When the component has its own focus trap, then it is managed by global trap stack by focus-trap.
1059+
*
1060+
* However if the component has no focus trap and is used inside another focus trap - there is an issue.
1061+
* By default popover content is rendered in body or other container, which is likely outside the current focus trap containers.
1062+
* It results in broken behavior from focus-trap.
1063+
*
1064+
* We need to pause all the focus traps for opening popover and then unpause them back after closing.
1065+
*/
1066+
intersectIntoCurrentFocusTrapStack() {
1067+
if (this.withFocusTrap) {
1068+
return
1069+
}
1070+
1071+
if (this.opened) {
1072+
this.externalFocusTrapStack = [...getTrapStack()]
1073+
for (const trap of this.externalFocusTrapStack) {
1074+
trap.pause()
1075+
}
1076+
} else {
1077+
for (const trap of this.externalFocusTrapStack) {
1078+
trap.unpause()
1079+
}
1080+
this.externalFocusTrapStack = []
1081+
}
1082+
},
1083+
10511084
/**
10521085
* Do we have exactly one Action and
10531086
* is it allowed as a standalone element?

0 commit comments

Comments
 (0)