Skip to content

Commit

Permalink
Merge pull request #3030 from nextcloud/fix/noid/actions-focus-trap
Browse files Browse the repository at this point in the history
Don't return focus after close-after-click
  • Loading branch information
PVince81 authored Aug 17, 2022
2 parents eb7cf3e + 6cf563b commit 2ea4bfb
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 54 deletions.
54 changes: 34 additions & 20 deletions src/components/ActionButton/ActionButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,52 @@ This component is made to be used inside of the [Actions](#Actions) component sl

```vue
<template>
<Actions>
<ActionButton @click="showMessage('Delete')">
<template #icon>
<Delete :size="20" />
</template>
Delete
</ActionButton>
<ActionButton :close-after-click="true" @click="showMessage('Delete and close menu')">
<template #icon>
<Delete :size="20" />
</template>
Delete and close
</ActionButton>
<ActionButton :disabled="true" @click="showMessage('Disabled')">
<template #icon>
<Delete :size="20" />
</template>
Disabled button
</ActionButton>
</Actions>
<div style="display: flex; align-items: center;">
<Actions>
<ActionButton @click="showMessage('Delete')">
<template #icon>
<Delete :size="20" />
</template>
Delete
</ActionButton>
<ActionButton :close-after-click="true" @click="showMessage('Delete and close menu')">
<template #icon>
<Delete :size="20" />
</template>
Delete and close
</ActionButton>
<ActionButton :close-after-click="true" @click="focusInput">
<template #icon>
<Plus :size="20" />
</template>
Create
</ActionButton>
<ActionButton :disabled="true" @click="showMessage('Disabled')">
<template #icon>
<Delete :size="20" />
</template>
Disabled button
</ActionButton>
</Actions>
<input ref="input" />
</div>
</template>
<script>
import Delete from 'vue-material-design-icons/Delete'
import Plus from 'vue-material-design-icons/Plus'
export default {
components: {
Delete,
Plus,
},
methods: {
showMessage(msg) {
alert(msg)
},
focusInput() {
this.$nextTick(() => this.$refs.input.focus())
},
},
}
</script>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Actions/Actions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -559,13 +559,15 @@ export default {
*/
this.$emit('open')
},
closeMenu(e) {
closeMenu(returnFocus = true) {
if (!this.opened) {
return
}
this.opened = false
this.$refs.popover.clearFocusTrap({ returnFocus })
/**
* Event emitted when the popover menu open state is changed
*
Expand Down Expand Up @@ -639,7 +641,7 @@ export default {
}
// Esc
if (event.keyCode === 27) {
this.closeMenu(event)
this.closeMenu()
event.preventDefault()
}
},
Expand Down Expand Up @@ -811,6 +813,7 @@ export default {
[
h('Popover',
{
ref: 'popover',
props: {
delay: 0,
handleResize: true,
Expand Down
75 changes: 44 additions & 31 deletions src/components/Popover/Popover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,12 @@ export default {
type: String,
default: '',
},
/**
* Enable popover focus trap
*/
focusTrap: {
type: Boolean,
default: false,
default: true,
},
},
Expand Down Expand Up @@ -142,10 +145,47 @@ export default {
},
beforeDestroy() {
this.afterHide()
this.clearFocusTrap()
},
methods: {
/**
* Add focus trap for accessibility.
*/
async useFocusTrap() {
await this.$nextTick()
if (!this.focusTrap) {
return
}
const el = this.$refs.popover?.$refs.popperContent?.$el
if (!el) {
return
}
this.$focusTrap = createFocusTrap(el, {
// Prevents to lose focus using esc key
// Focus will be release when popover be hide
escapeDeactivates: false,
allowOutsideClick: true,
})
this.$focusTrap.activate()
},
/**
* Remove focus trap
*
* @param {object} options The configuration options for focusTrap
*/
clearFocusTrap(options = {}) {
try {
this.$focusTrap?.deactivate(options)
this.$focusTrap = null
} catch (err) {
console.warn(err)
}
},
afterShow() {
/**
* Triggered after the tooltip was visually displayed.
Expand All @@ -155,41 +195,14 @@ export default {
* tooltip is already visible and in the DOM.
*/
this.$emit('after-show')
/**
* Add focus trap for accessibility.
*/
this.$nextTick(() => {
if (!this.focusTrap) {
return
}
const el = this.$refs.popover?.$refs.popperContent?.$el
if (!el) {
return
}
this.$focusTrap = createFocusTrap(el, {
// Prevents to lose focus using esc key
// Focus will be release when popover be hide
escapeDeactivates: false,
allowOutsideClick: true,
})
this.$focusTrap.activate()
})
this.useFocusTrap()
},
afterHide() {
/**
* Triggered after the tooltip was visually hidden.
*/
this.$emit('after-hide')
/**
* Remove focus trap
*/
this.$focusTrap?.deactivate()
this.$focusTrap = null
this.clearFocusTrap()
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion src/mixins/actionText.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default {
if (this.closeAfterClick) {
const parent = GetParent(this, 'Actions')
if (parent && parent.closeMenu) {
parent.closeMenu()
parent.closeMenu(false)
}
}
},
Expand Down

0 comments on commit 2ea4bfb

Please sign in to comment.