Skip to content

Commit 3d5e511

Browse files
PeikyLiuilyaliaoautofix-ci[bot]
authored
feat(useFocusTrap): expose updateContainerElements for dynamic contai… (#4849)
Co-authored-by: IlyaL <ilyaliao324@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent f298252 commit 3d5e511

File tree

2 files changed

+71
-23
lines changed

2 files changed

+71
-23
lines changed

packages/integrations/useFocusTrap/index.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,40 @@ const { hasFocus, activate, deactivate } = useFocusTrap([targetOne, targetTwo])
7676
</template>
7777
```
7878

79+
**Dynamic Focus Target**
80+
81+
```vue
82+
<script setup lang="ts">
83+
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
84+
import { computed, shallowRef, useTemplateRef } from 'vue'
85+
86+
const left = useTemplateRef('left')
87+
const right = useTemplateRef('right')
88+
const currentRef = shallowRef<'left' | 'right'>('left')
89+
90+
const target = computed(() =>
91+
currentRef.value === 'left'
92+
? left
93+
: currentRef.value === 'right'
94+
? right
95+
: null,
96+
)
97+
98+
const { activate } = useFocusTrap(target)
99+
</script>
100+
101+
<template>
102+
<div>
103+
<div ref="left" class="left">
104+
...
105+
</div>
106+
<div ref="right" class="right">
107+
...
108+
</div>
109+
</div>
110+
</template>
111+
```
112+
79113
**Automatically Focus**
80114

81115
```vue

packages/integrations/useFocusTrap/index.ts

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export interface UseFocusTrapReturn {
6161
* @see https://vueuse.org/useFocusTrap
6262
*/
6363
export function useFocusTrap(
64-
target: Arrayable<MaybeRefOrGetter<string> | MaybeComputedElementRef>,
64+
target: MaybeRefOrGetter<Arrayable<MaybeRefOrGetter<string> | MaybeComputedElementRef>>,
6565
options: UseFocusTrapOptions = {},
6666
): UseFocusTrapReturn {
6767
let trap: undefined | FocusTrap
@@ -102,28 +102,42 @@ export function useFocusTrap(
102102
(els) => {
103103
if (!els.length)
104104
return
105-
106-
trap = createFocusTrap(els, {
107-
...focusTrapOptions,
108-
onActivate() {
109-
hasFocus.value = true
110-
111-
// Apply if user provided onActivate option
112-
if (options.onActivate)
113-
options.onActivate()
114-
},
115-
onDeactivate() {
116-
hasFocus.value = false
117-
118-
// Apply if user provided onDeactivate option
119-
if (options.onDeactivate)
120-
options.onDeactivate()
121-
},
122-
})
123-
124-
// Focus if immediate is set to true
125-
if (immediate)
126-
activate()
105+
if (!trap) {
106+
// create the trap
107+
trap = createFocusTrap(els, {
108+
...focusTrapOptions,
109+
onActivate() {
110+
hasFocus.value = true
111+
112+
// Apply if user provided onActivate option
113+
if (options.onActivate)
114+
options.onActivate()
115+
},
116+
onDeactivate() {
117+
hasFocus.value = false
118+
119+
// Apply if user provided onDeactivate option
120+
if (options.onDeactivate)
121+
options.onDeactivate()
122+
},
123+
})
124+
125+
// Focus if immediate is set to true
126+
if (immediate)
127+
activate()
128+
}
129+
else {
130+
// get the active state of the trap
131+
const isActive = trap?.active
132+
133+
// update the container elements
134+
trap?.updateContainerElements(els)
135+
136+
// if the trap is not active and immediate is set to true, activate the trap
137+
if (!isActive && immediate) {
138+
activate()
139+
}
140+
}
127141
},
128142
{ flush: 'post' },
129143
)

0 commit comments

Comments
 (0)