Skip to content

Commit

Permalink
fix(files): move header actions out from the table
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ShGKme authored and backportbot-nextcloud[bot] committed Jan 10, 2024
1 parent 9aaead8 commit 41183b9
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 49 deletions.
86 changes: 40 additions & 46 deletions apps/files/src/components/FilesListTableHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
6 changes: 3 additions & 3 deletions apps/files/src/components/FilesListTableHeaderActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -38,7 +38,7 @@
{{ action.displayName(nodes, currentView) }}
</NcActionButton>
</NcActions>
</th>
</div>
</template>

<script lang="ts">
Expand Down Expand Up @@ -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;
Expand Down
35 changes: 35 additions & 0 deletions apps/files/src/components/FilesListVirtual.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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'
Expand All @@ -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',
Expand All @@ -94,6 +101,7 @@ export default defineComponent({
FilesListTableFooter,
FilesListTableHeader,
VirtualList,
FilesListTableHeaderActions,
},
mixins: [
Expand All @@ -117,8 +125,10 @@ export default defineComponent({
setup() {
const userConfigStore = useUserConfigStore()
const selectionStore = useSelectionStore()
return {
userConfigStore,
selectionStore,
}
},
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -298,6 +316,7 @@ export default defineComponent({
--clickable-area: 44px;
--icon-preview-size: 32px;
position: relative;
overflow: auto;
height: 100%;
will-change: scroll-position;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions apps/files/src/components/VirtualList.vue
Original file line number Diff line number Diff line change
@@ -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" />
Expand Down

0 comments on commit 41183b9

Please sign in to comment.