aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorGrigorii K. Shartsev <me@shgk.me>2024-01-08 16:10:30 +0100
committerGrigorii K. Shartsev <me@shgk.me>2024-01-10 17:52:24 +0100
commitb1a9017f5fbe15a6fe3ccb592ff000661ce2e3ad (patch)
tree88d97b3748bd766a0102899049ccf43ae9750d9b /apps
parentb2aa27f3e38ba156c21e345cc13dbcd21b1c5e1b (diff)
downloadnextcloud-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.vue86
-rw-r--r--apps/files/src/components/FilesListTableHeaderActions.vue6
-rw-r--r--apps/files/src/components/FilesListVirtual.vue35
-rw-r--r--apps/files/src/components/VirtualList.vue4
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" />