Skip to content

Commit

Permalink
Merge pull request #41197 from nextcloud/fix/keep-focus-on-app-order
Browse files Browse the repository at this point in the history
fix(theming): Ensure focus is kept on the button when reordering
  • Loading branch information
susnux authored Oct 30, 2023
2 parents ee9cad7 + 7bb2aec commit 1215379
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 11 deletions.
17 changes: 16 additions & 1 deletion apps/theming/src/components/AppOrderSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<ol ref="listElement" data-cy-app-order class="order-selector">
<AppOrderSelectorElement v-for="app,index in appList"
:key="`${app.id}${renderCount}`"
ref="selectorElements"
:app="app"
:is-first="index === 0 || !!appList[index - 1].default"
:is-last="index === value.length - 1"
Expand All @@ -14,7 +15,7 @@

<script lang="ts">
import { useSortable } from '@vueuse/integrations/useSortable'
import { PropType, computed, defineComponent, ref } from 'vue'
import { PropType, computed, defineComponent, onUpdated, ref } from 'vue'
import AppOrderSelectorElement from './AppOrderSelectorElement.vue'
Expand Down Expand Up @@ -81,6 +82,19 @@ export default defineComponent({
*/
useSortable(listElement, appList, { filter: '.order-selector-element--disabled' })
/**
* Array of all AppOrderSelectorElement components used to for keeping the focus after button click
*/
const selectorElements = ref<InstanceType<typeof AppOrderSelectorElement>[]>([])
/**
* We use the updated hook here to verify all selector elements keep the focus on the last pressed button
* This is needed to be done in this component to make sure Sortable.JS has finished sorting the elements before focussing an element
*/
onUpdated(() => {
selectorElements.value.forEach(element => element.keepFocus())
})
/**
* Handle element is moved up
* @param index The index of the element that is moved
Expand Down Expand Up @@ -119,6 +133,7 @@ export default defineComponent({
moveUp,
renderCount,
selectorElements,
}
},
})
Expand Down
12 changes: 8 additions & 4 deletions apps/theming/src/components/AppOrderSelectorElement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import type { PropType } from 'vue'

import { translate as t } from '@nextcloud/l10n'
import { defineComponent, nextTick, onUpdated, ref } from 'vue'
import { defineComponent, nextTick, ref } from 'vue'

import IconArrowDown from 'vue-material-design-icons/ArrowDown.vue'
import IconArrowUp from 'vue-material-design-icons/ArrowUp.vue'
Expand Down Expand Up @@ -116,10 +116,12 @@ export default defineComponent({
}

/**
* onUpdated hook is used to reset the focus on the last used button (if requested)
* Reset the focus on the last used button.
* If the button is now visible anymore (because this element is the first/last) then the opposite button is focussed
*
* This function is exposed to the "AppOrderSelector" component which triggers this when the list was successfully rerendered
*/
onUpdated(() => {
const keepFocus = () => {
if (needsFocus !== 0) {
// focus requested
if ((needsFocus === 1 || props.isLast) && !props.isFirst) {
Expand All @@ -130,7 +132,7 @@ export default defineComponent({
}
}
needsFocus = 0
})
}

return {
buttonUp,
Expand All @@ -139,6 +141,8 @@ export default defineComponent({
moveUp,
moveDown,

keepFocus,

t,
}
},
Expand Down
4 changes: 2 additions & 2 deletions dist/theming-admin-theming.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/theming-admin-theming.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/theming-personal-theming.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/theming-personal-theming.js.map

Large diffs are not rendered by default.

0 comments on commit 1215379

Please sign in to comment.