Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit ced42f1

Browse files
Merge pull request #122 from chakra-ui/fix/modal-focus-lock
fix: rewrite logic for modal focus lock
2 parents 60deb53 + 8223433 commit ced42f1

32 files changed

+912
-3665
lines changed

.changeset/gorgeous-tables-mate.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
"@chakra-ui/c-accordion": patch
3+
"@chakra-ui/c-alert": patch
4+
"@chakra-ui/c-breadcrumb": patch
5+
"@chakra-ui/c-button": patch
6+
"@chakra-ui/c-close-button": patch
7+
"@chakra-ui/c-code": patch
8+
"@chakra-ui/c-color-mode": patch
9+
"@chakra-ui/c-flex": patch
10+
"@chakra-ui/c-focus-lock": patch
11+
"@chakra-ui/c-form-control": patch
12+
"@chakra-ui/c-icon": patch
13+
"@chakra-ui/c-input": patch
14+
"@chakra-ui/c-modal": patch
15+
"@chakra-ui/c-motion": patch
16+
"@chakra-ui/c-popper": patch
17+
"@chakra-ui/c-portal": patch
18+
"@chakra-ui/c-reset": patch
19+
"@chakra-ui/c-scroll-lock": patch
20+
"@chakra-ui/c-spinner": patch
21+
"@chakra-ui/c-theme-provider": patch
22+
"@chakra-ui/c-visually-hidden": patch
23+
"@chakra-ui/vue-next": patch
24+
"@chakra-ui/vue-layout": patch
25+
"@chakra-ui/nuxt-next": patch
26+
"@chakra-ui/vue-system": patch
27+
"@chakra-ui/vue-test-utils": patch
28+
"@chakra-ui/vue-theme": patch
29+
"@chakra-ui/vue-theme-tools": patch
30+
"@chakra-ui/vue-utils": patch
31+
"@chakra-ui/vue-a11y": patch
32+
"@chakra-ui/vue-composables": patch
33+
"@chakra-ui/vue-auto-import": patch
34+
"@chakra-ui/vue-docs": patch
35+
---
36+
37+
Rewrite focus trap logic

packages/c-focus-lock/examples/with-focus-lock-component.vue

Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111
rounded="lg"
1212
border-color="gray.400"
1313
d="inline-block"
14-
@activate="handleActivate"
15-
@deactivate="handleDeactivate"
16-
:allow-outside-click="false"
17-
:initial-focus-ref="() => initialFocusRef"
18-
#default="{ hasFocus, deactivate }"
14+
#default="{ enabled, deactivate }"
1915
pos="relative"
2016
v-if="isActive"
2117
>
@@ -26,7 +22,7 @@
2622
right="10px"
2723
@click="deactivate"
2824
></c-close-button>
29-
<chakra.pre> Focus trap enabled: {{ hasFocus }} </chakra.pre>
25+
<chakra.pre> Focus trap enabled: {{ enabled }} </chakra.pre>
3026
<chakra.p mb="2">Inside focus trap</chakra.p>
3127
<c-button color-scheme="teal"> Login </c-button>
3228
<c-button :ref="initialFocus" color-scheme="yellow" mx="2"
@@ -35,28 +31,28 @@
3531
<c-button left-icon="user" color-scheme="red"
3632
>Delete account</c-button
3733
>
38-
<chakra.pre> Focus trap enabled: {{ hasFocus }} </chakra.pre>
34+
<chakra.pre> Focus trap enabled: {{ enabled }} </chakra.pre>
3935
<chakra.p mb="2">Inside focus trap</chakra.p>
4036
<c-button color-scheme="teal"> Login </c-button>
4137
<c-button color-scheme="yellow" mx="2">Initial focus!</c-button>
4238
<c-button left-icon="user" color-scheme="red"
4339
>Delete account</c-button
4440
>
45-
<chakra.pre> Focus trap enabled: {{ hasFocus }} </chakra.pre>
41+
<chakra.pre> Focus trap enabled: {{ enabled }} </chakra.pre>
4642
<chakra.p mb="2">Inside focus trap</chakra.p>
4743
<c-button color-scheme="teal"> Login </c-button>
4844
<c-button color-scheme="yellow" mx="2">Initial focus!</c-button>
4945
<c-button left-icon="user" color-scheme="red"
5046
>Delete account</c-button
5147
>
52-
<chakra.pre> Focus trap enabled: {{ hasFocus }} </chakra.pre>
48+
<chakra.pre> Focus trap enabled: {{ enabled }} </chakra.pre>
5349
<chakra.p mb="2">Inside focus trap</chakra.p>
5450
<c-button color-scheme="teal"> Login </c-button>
5551
<c-button color-scheme="yellow" mx="2">Initial focus!</c-button>
5652
<c-button left-icon="user" color-scheme="red"
5753
>Delete account</c-button
5854
>
59-
<chakra.pre> Focus trap enabled: {{ hasFocus }} </chakra.pre>
55+
<chakra.pre> Focus trap enabled: {{ enabled }} </chakra.pre>
6056
<chakra.p mb="2">Inside focus trap</chakra.p>
6157
<c-button color-scheme="teal"> Login </c-button>
6258
<c-button color-scheme="yellow" mx="2">Initial focus!</c-button>
@@ -90,56 +86,33 @@
9086
</chakra.div>
9187
</template>
9288

93-
<script lang="ts">
94-
import { useRef } from '@chakra-ui/vue-utils'
95-
import { defineComponent, ref, watch } from 'vue'
96-
import { CFocusLock } from '../src/c-focus-lock'
89+
<script lang="ts" setup>
90+
import { chakra } from "@chakra-ui/vue-next"
91+
import { useRef } from "@chakra-ui/vue-utils"
92+
import { ref } from "vue"
93+
import { CFocusLock } from "../src/c-focus-lock"
9794
98-
if (!document.getElementById('new-target')) {
99-
const target = document.createElement('div')
100-
target.style.display = 'inline-block'
101-
target.style.position = 'absolute'
102-
target.style.top = '50px'
103-
target.style.left = '250px'
95+
if (!document.getElementById("new-target")) {
96+
const target = document.createElement("div")
97+
target.style.display = "inline-block"
98+
target.style.position = "absolute"
99+
target.style.top = "50px"
100+
target.style.left = "250px"
104101
105-
target.id = 'new-target'
102+
target.id = "new-target"
106103
document.body.appendChild(target)
107104
}
105+
const isActive = ref(false)
106+
const [finalFocus, finalFocusRef] = useRef()
107+
const [initialFocus, initialFocusRef] = useRef()
108108
109-
export default defineComponent({
110-
components: {
111-
CFocusLock,
112-
},
113-
setup() {
114-
const isActive = ref(false)
115-
const [finalFocus, finalFocusRef] = useRef()
116-
const [initialFocus, initialFocusRef] = useRef()
117-
118-
const handleActivate = () => {
119-
console.log('focuslock activated')
120-
}
121-
122-
const handleDeactivate = () => {
123-
console.log('focuslock deactivated')
124-
isActive.value = false
125-
setTimeout(() => {})
126-
}
127-
128-
watch(isActive, () => {
129-
setTimeout(() => {
130-
isActive.value = !isActive.value
131-
}, 3000)
132-
})
109+
const handleActivate = () => {
110+
console.log("focuslock activated")
111+
}
133112
134-
return {
135-
isActive,
136-
handleActivate,
137-
handleDeactivate,
138-
finalFocus,
139-
finalFocusRef,
140-
initialFocus,
141-
initialFocusRef,
142-
}
143-
},
144-
})
113+
const handleDeactivate = () => {
114+
console.log("focuslock deactivated")
115+
isActive.value = false
116+
setTimeout(() => {})
117+
}
145118
</script>

packages/c-focus-lock/examples/with-focus-lock-hook.vue

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<c-portal to="#new-target">
88
<c-motion type="fade">
99
<chakra.div
10-
:ref="lock"
10+
ref="_target"
1111
p="4"
1212
border="4px dashed"
1313
rounded="lg"
@@ -24,9 +24,7 @@
2424
></c-close-button>
2525
<chakra.p mb="2">Inside focus trap</chakra.p>
2626
<c-button color-scheme="teal"> Login </c-button>
27-
<c-button color-scheme="yellow" :ref="initialFocus" mx="2"
28-
>Initial focus!</c-button
29-
>
27+
<c-button color-scheme="yellow" mx="2">Initial focus!</c-button>
3028
<c-button left-icon="user" color-scheme="red"
3129
>Delete account</c-button
3230
>
@@ -49,15 +47,16 @@
4947
<c-button @click="activate" ml="3" color-scheme="blue">Enable</c-button>
5048
</chakra.div>
5149
<chakra.pre font-weight="bold">
52-
Focus lock enabled: {{ hasFocus }}
50+
Focus lock enabled: {{ isLocked }}
5351
</chakra.pre>
5452
</chakra.div>
5553
</template>
5654

5755
<script setup lang="ts">
5856
import { chakra } from "@chakra-ui/vue-next"
59-
import { useFocusLock } from "../src/use-focus-lock"
60-
import { ref } from "vue"
57+
import { ref, watch, watchEffect } from "vue"
58+
import { useFocusTrap } from "../src/use-focus-trap"
59+
import { unrefElement } from "@chakra-ui/vue-utils"
6160
6261
const isLocked = ref(false)
6362
@@ -72,26 +71,32 @@ if (!document.getElementById("new-target")) {
7271
document.body.appendChild(target)
7372
}
7473
75-
const {
76-
hasFocus,
77-
lock,
78-
activate: lockactivate,
79-
deactivate: lockdeactivate,
80-
initialFocus,
81-
} = useFocusLock({
82-
escapeDeactivates: false,
83-
delayInitialFocus: true,
84-
immediate: true,
85-
})
74+
const _target = ref()
75+
const containers = ref<Set<HTMLElement>>(new Set())
76+
77+
watchEffect(
78+
(onInvalidate) => {
79+
let el: HTMLElement
80+
if (_target.value) {
81+
el = unrefElement(_target)
82+
containers.value.add(el)
83+
}
84+
85+
console.log("Adding containers", containers.value)
86+
87+
onInvalidate(() => {
88+
containers.value.delete(el)
89+
})
90+
},
91+
{ flush: "post" }
92+
)
93+
useFocusTrap(containers, ref(true))
8694
8795
const activate = async () => {
8896
isLocked.value = true
89-
// setTimeout(lockactivate)
90-
setTimeout(lockactivate)
9197
}
9298
9399
const deactivate = () => {
94-
lockdeactivate()
95100
isLocked.value = false
96101
}
97102
</script>

packages/c-focus-lock/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
},
3030
"dependencies": {
3131
"@chakra-ui/utils": "^1.9.1",
32+
"@chakra-ui/vue-composables": "0.1.0-alpha.7",
3233
"@chakra-ui/vue-system": "0.1.0-alpha.8",
3334
"@chakra-ui/vue-utils": "0.1.0-alpha.8",
3435
"focus-trap": "^6.3.0"

0 commit comments

Comments
 (0)