diff options
author | Grigorii K. Shartsev <me@shgk.me> | 2024-01-08 16:10:30 +0100 |
---|---|---|
committer | Grigorii K. Shartsev <me@shgk.me> | 2024-01-10 17:52:24 +0100 |
commit | b1a9017f5fbe15a6fe3ccb592ff000661ce2e3ad (patch) | |
tree | 88d97b3748bd766a0102899049ccf43ae9750d9b /apps | |
parent | b2aa27f3e38ba156c21e345cc13dbcd21b1c5e1b (diff) | |
download | nextcloud-server-b1a9017f5fbe15a6fe3ccb592ff000661ce2e3ad.tar.gz nextcloud-server-b1a9017f5fbe15a6fe3ccb592ff000661ce2e3ad.zip |
fix(files): move header actions out from the table
Having actions in the table header is no valid for a11y and counts as a column name.
Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/src/components/FilesListTableHeader.vue | 86 | ||||
-rw-r--r-- | apps/files/src/components/FilesListTableHeaderActions.vue | 6 | ||||
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 35 | ||||
-rw-r--r-- | apps/files/src/components/VirtualList.vue | 4 |
4 files changed, 82 insertions, 49 deletions
diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue index 285036a2f94..c679b2068c1 100644 --- a/apps/files/src/components/FilesListTableHeader.vue +++ b/apps/files/src/components/FilesListTableHeader.vue @@ -26,53 +26,47 @@ <NcCheckboxRadioSwitch v-bind="selectAllBind" @update:checked="onToggleAll" /> </th> - <!-- Actions multiple if some are selected --> - <FilesListTableHeaderActions v-if="!isNoneSelected" - :current-view="currentView" - :selected-nodes="selectedNodes" /> - <!-- Columns display --> - <template v-else> - <!-- Link to file --> - <th class="files-list__column files-list__row-name files-list__column--sortable" - :aria-sort="ariaSortForMode('basename')"> - <!-- Icon or preview --> - <span class="files-list__row-icon" /> - - <!-- Name --> - <FilesListTableHeaderButton :name="t('files', 'Name')" mode="basename" /> - </th> - - <!-- Actions --> - <th class="files-list__row-actions" /> - - <!-- Size --> - <th v-if="isSizeAvailable" - :class="{'files-list__column--sortable': isSizeAvailable}" - class="files-list__column files-list__row-size" - :aria-sort="ariaSortForMode('size')"> - <FilesListTableHeaderButton :name="t('files', 'Size')" mode="size" /> - </th> - - <!-- Mtime --> - <th v-if="isMtimeAvailable" - :class="{'files-list__column--sortable': isMtimeAvailable}" - class="files-list__column files-list__row-mtime" - :aria-sort="ariaSortForMode('mtime')"> - <FilesListTableHeaderButton :name="t('files', 'Modified')" mode="mtime" /> - </th> - - <!-- Custom views columns --> - <th v-for="column in columns" - :key="column.id" - :class="classForColumn(column)" - :aria-sort="ariaSortForMode(column.id)"> - <FilesListTableHeaderButton v-if="!!column.sort" :name="column.title" :mode="column.id" /> - <span v-else> - {{ column.title }} - </span> - </th> - </template> + + <!-- Link to file --> + <th class="files-list__column files-list__row-name files-list__column--sortable" + :aria-sort="ariaSortForMode('basename')"> + <!-- Icon or preview --> + <span class="files-list__row-icon" /> + + <!-- Name --> + <FilesListTableHeaderButton :name="t('files', 'Name')" mode="basename" /> + </th> + + <!-- Actions --> + <th class="files-list__row-actions" /> + + <!-- Size --> + <th v-if="isSizeAvailable" + class="files-list__column files-list__row-size" + :class="{ 'files-list__column--sortable': isSizeAvailable }" + :aria-sort="ariaSortForMode('size')"> + <FilesListTableHeaderButton :name="t('files', 'Size')" mode="size" /> + </th> + + <!-- Mtime --> + <th v-if="isMtimeAvailable" + class="files-list__column files-list__row-mtime" + :class="{ 'files-list__column--sortable': isMtimeAvailable }" + :aria-sort="ariaSortForMode('mtime')"> + <FilesListTableHeaderButton :name="t('files', 'Modified')" mode="mtime" /> + </th> + + <!-- Custom views columns --> + <th v-for="column in columns" + :key="column.id" + :class="classForColumn(column)" + :aria-sort="ariaSortForMode(column.id)"> + <FilesListTableHeaderButton v-if="!!column.sort" :name="column.title" :mode="column.id" /> + <span v-else> + {{ column.title }} + </span> + </th> </tr> </template> diff --git a/apps/files/src/components/FilesListTableHeaderActions.vue b/apps/files/src/components/FilesListTableHeaderActions.vue index 73b9c429a3d..c65f5fd9b4f 100644 --- a/apps/files/src/components/FilesListTableHeaderActions.vue +++ b/apps/files/src/components/FilesListTableHeaderActions.vue @@ -20,7 +20,7 @@ - --> <template> - <th class="files-list__column files-list__row-actions-batch" colspan="2"> + <div class="files-list__column files-list__row-actions-batch"> <NcActions ref="actionsMenu" :disabled="!!loading || areSomeNodesLoading" :force-name="true" @@ -38,7 +38,7 @@ {{ action.displayName(nodes, currentView) }} </NcActionButton> </NcActions> - </th> + </div> </template> <script lang="ts"> @@ -220,7 +220,7 @@ export default Vue.extend({ flex: 1 1 100% !important; // Remove when https://github.com/nextcloud/nextcloud-vue/pull/3936 is merged - ::v-deep .button-vue__wrapper { + :deep(.button-vue__wrapper) { width: 100%; span.button-vue__text { overflow: hidden; diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index 88bb7e2076a..9ae520b6e9d 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -33,6 +33,11 @@ }" :scroll-to-index="scrollToIndex" :caption="caption"> + <template v-if="!isNoneSelected" #header-overlay> + <FilesListTableHeaderActions :current-view="currentView" + :selected-nodes="selectedNodes" /> + </template> + <template #before> <!-- Headers --> <FilesListHeader v-for="header in sortedHeaders" @@ -76,6 +81,7 @@ import { defineComponent } from 'vue' import { action as sidebarAction } from '../actions/sidebarAction.ts' import { useUserConfigStore } from '../store/userconfig.ts' +import { useSelectionStore } from '../store/selection.js' import FileEntry from './FileEntry.vue' import FileEntryGrid from './FileEntryGrid.vue' @@ -85,6 +91,7 @@ import FilesListTableHeader from './FilesListTableHeader.vue' import filesListWidthMixin from '../mixins/filesListWidth.ts' import VirtualList from './VirtualList.vue' import logger from '../logger.js' +import FilesListTableHeaderActions from './FilesListTableHeaderActions.vue' export default defineComponent({ name: 'FilesListVirtual', @@ -94,6 +101,7 @@ export default defineComponent({ FilesListTableFooter, FilesListTableHeader, VirtualList, + FilesListTableHeaderActions, }, mixins: [ @@ -117,8 +125,10 @@ export default defineComponent({ setup() { const userConfigStore = useUserConfigStore() + const selectionStore = useSelectionStore() return { userConfigStore, + selectionStore, } }, @@ -185,6 +195,14 @@ export default defineComponent({ const virtualListNote = t('files', 'This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list.') return `${viewCaption}\n${sortableCaption}\n${virtualListNote}` }, + + selectedNodes() { + return this.selectionStore.selected + }, + + isNoneSelected() { + return this.selectedNodes.length === 0 + }, }, watch: { @@ -298,6 +316,7 @@ export default defineComponent({ --clickable-area: 44px; --icon-preview-size: 32px; + position: relative; overflow: auto; height: 100%; will-change: scroll-position; @@ -333,6 +352,22 @@ export default defineComponent({ display: block; } + .files-list__thead-overlay { + position: absolute; + top: 0; + left: var(--row-height); // Save space for a row checkbox + right: 0; + z-index: 1000; + + display: flex; + align-items: center; + + // Reuse row styles + background-color: var(--color-main-background); + border-bottom: 1px solid var(--color-border); + height: var(--row-height); + } + .files-list__thead, .files-list__tfoot { display: flex; diff --git a/apps/files/src/components/VirtualList.vue b/apps/files/src/components/VirtualList.vue index 0a99f19bb5f..77454772f55 100644 --- a/apps/files/src/components/VirtualList.vue +++ b/apps/files/src/components/VirtualList.vue @@ -1,5 +1,9 @@ <template> <div class="files-list" data-cy-files-list> + <div v-if="!!$scopedSlots['header-overlay']" class="files-list__thead-overlay"> + <slot name="header-overlay" /> + </div> + <!-- Header --> <div ref="before" class="files-list__before"> <slot name="before" /> |