From 10c674d201a5ce6a2023f78983d8f57ffe1a683b Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Fri, 20 Feb 2026 10:43:37 +0100 Subject: [PATCH] fix(files): fix tab navigation from select all checkbox to batch actions Signed-off-by: skjnldsv --- .../src/components/FilesListTableHeader.vue | 23 +++++++++++++ .../FilesListTableHeaderActions.vue | 33 ++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue index ed9e22d25fd..28a3995bb00 100644 --- a/apps/files/src/components/FilesListTableHeader.vue +++ b/apps/files/src/components/FilesListTableHeader.vue @@ -9,6 +9,7 @@ @keyup.esc.exact="resetSelection"> @@ -79,6 +80,7 @@ import { t } from '@nextcloud/l10n' import { useHotKey } from '@nextcloud/vue/composables/useHotKey' import { defineComponent } from 'vue' import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' +import { FILE_LIST_HEAD_FIRST_BATCH_ACTION_ID } from './FilesListTableHeaderActions.vue' import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue' import { useFileListWidth } from '../composables/useFileListWidth.ts' import { useRouteParameters } from '../composables/useRouteParameters.ts' @@ -88,6 +90,8 @@ import { useActiveStore } from '../store/active.ts' import { useFilesStore } from '../store/files.ts' import { useSelectionStore } from '../store/selection.ts' +export const FILES_LIST_HEADER_SELECT_ALL_CHECKBOX_ID = 'files-list-header-select-all-checkbox' + export default defineComponent({ name: 'FilesListTableHeader', @@ -137,6 +141,8 @@ export default defineComponent({ directory, isNarrow, + + FILES_LIST_HEADER_SELECT_ALL_CHECKBOX_ID, } }, @@ -196,6 +202,11 @@ export default defineComponent({ }) }, + mounted() { + const selectAllCheckbox = document.getElementById(FILES_LIST_HEADER_SELECT_ALL_CHECKBOX_ID) + selectAllCheckbox?.addEventListener('keydown', this.onSelectAllCheckboxFocusOut) + }, + methods: { ariaSortForMode(mode: string): 'ascending' | 'descending' | undefined { if (this.sortingMode === mode) { @@ -231,6 +242,18 @@ export default defineComponent({ this.selectionStore.reset() }, + onSelectAllCheckboxFocusOut(event: KeyboardEvent) { + // If the user tabbed further and we have a batch action to tab to + const firstBatchActionButton = document.getElementById(FILE_LIST_HEAD_FIRST_BATCH_ACTION_ID) + if (event.code === 'Tab' && !event.shiftKey && !event.metaKey && firstBatchActionButton) { + event.preventDefault() + event.stopPropagation() + + firstBatchActionButton.focus() + logger.debug('Focusing first batch action button') + } + }, + t, }, }) diff --git a/apps/files/src/components/FilesListTableHeaderActions.vue b/apps/files/src/components/FilesListTableHeaderActions.vue index b522c89a09d..a277ed301b9 100644 --- a/apps/files/src/components/FilesListTableHeaderActions.vue +++ b/apps/files/src/components/FilesListTableHeaderActions.vue @@ -16,7 +16,8 @@ @close="openedSubmenu = null">