Skip to content

Commit 06091d1

Browse files
committed
feat(files): better breakpoints and sidebar responsive design
Signed-off-by: John Molakvoæ <[email protected]>
1 parent f37b29e commit 06091d1

File tree

12 files changed

+94
-59
lines changed

12 files changed

+94
-59
lines changed

apps/files/src/components/FileEntry.vue

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
<script lang='ts'>
105105
import { debounce } from 'debounce'
106106
import { formatFileSize } from '@nextcloud/files'
107-
import { Fragment } from 'vue-fragment'
107+
import { Fragment } from 'vue-frag'
108108
import { join } from 'path'
109109
import { showError, showSuccess } from '@nextcloud/dialogs'
110110
import { translate } from '@nextcloud/l10n'
@@ -115,7 +115,6 @@ import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
115115
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
116116
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
117117
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
118-
import isMobileMixin from '@nextcloud/vue/dist/Mixins/isMobile.js'
119118
import Vue from 'vue'
120119
121120
import { getFileActions } from '../services/FileAction.ts'
@@ -147,10 +146,6 @@ export default Vue.extend({
147146
NcLoadingIcon,
148147
},
149148
150-
mixins: [
151-
isMobileMixin,
152-
],
153-
154149
props: {
155150
active: {
156151
type: Boolean,
@@ -172,6 +167,10 @@ export default Vue.extend({
172167
type: Array,
173168
required: true,
174169
},
170+
filesListWidth: {
171+
type: Number,
172+
default: 0,
173+
},
175174
},
176175
177176
setup() {
@@ -207,6 +206,10 @@ export default Vue.extend({
207206
},
208207
209208
columns() {
209+
// Hide columns if the list is too small
210+
if (this.filesListWidth < 512) {
211+
return []
212+
}
210213
return this.currentView?.columns || []
211214
},
212215
@@ -300,14 +303,14 @@ export default Vue.extend({
300303
},
301304
302305
enabledInlineActions() {
303-
if (this.isMobile) {
306+
if (this.filesListWidth < 768) {
304307
return []
305308
}
306309
return this.enabledActions.filter(action => action?.inline?.(this.source, this.currentView))
307310
},
308311
309312
enabledMenuActions() {
310-
if (this.isMobile) {
313+
if (this.filesListWidth < 768) {
311314
return this.enabledActions
312315
}
313316

apps/files/src/components/FilesListFooter.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
<td class="files-list__row-actions" />
3939

4040
<!-- Size -->
41-
<td v-if="isSizeAvailable" class="files-list__column files-list__row-size">
41+
<td v-if="isSizeAvailable"
42+
class="files-list__column files-list__row-size">
4243
<span>{{ totalSize }}</span>
4344
</td>
4445

@@ -78,6 +79,10 @@ export default Vue.extend({
7879
type: String,
7980
default: '',
8081
},
82+
filesListWidth: {
83+
type: Number,
84+
default: 0,
85+
},
8186
},
8287
8388
setup() {
@@ -112,6 +117,10 @@ export default Vue.extend({
112117
},
113118
114119
columns() {
120+
// Hide columns if the list is too small
121+
if (this.filesListWidth < 512) {
122+
return []
123+
}
115124
return this.currentView?.columns || []
116125
},
117126

apps/files/src/components/FilesListHeader.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ export default Vue.extend({
102102
type: Array,
103103
required: true,
104104
},
105+
filesListWidth: {
106+
type: Number,
107+
default: 0,
108+
},
105109
},
106110
107111
setup() {
@@ -123,6 +127,10 @@ export default Vue.extend({
123127
},
124128
125129
columns() {
130+
// Hide columns if the list is too small
131+
if (this.filesListWidth < 512) {
132+
return []
133+
}
126134
return this.currentView?.columns || []
127135
},
128136

apps/files/src/components/FilesListHeaderActions.vue

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
:disabled="!!loading || areSomeNodesLoading"
2626
:force-title="true"
2727
:inline="inlineActions"
28-
:menu-title="inlineActions === 0 ? t('files', 'Actions') : null"
28+
:menu-title="inlineActions <= 1 ? t('files', 'Actions') : null"
2929
:open.sync="openedMenu">
3030
<NcActionButton v-for="action in enabledActions"
3131
:key="action.id"
@@ -53,7 +53,7 @@ import { getFileActions } from '../services/FileAction.ts'
5353
import { useActionsMenuStore } from '../store/actionsmenu.ts'
5454
import { useFilesStore } from '../store/files.ts'
5555
import { useSelectionStore } from '../store/selection.ts'
56-
import clientWidthMixin from '../mixins/clientWidth.ts'
56+
import filesListWidthMixin from '../mixins/filesListWidth.ts'
5757
import CustomSvgIconRender from './CustomSvgIconRender.vue'
5858
import logger from '../logger.js'
5959
@@ -71,7 +71,7 @@ export default Vue.extend({
7171
},
7272
7373
mixins: [
74-
clientWidthMixin,
74+
filesListWidthMixin,
7575
],
7676
7777
props: {
@@ -130,10 +130,13 @@ export default Vue.extend({
130130
},
131131
132132
inlineActions() {
133-
if (this.clientWidth < 480) {
133+
if (this.filesListWidth < 512) {
134+
return 0
135+
}
136+
if (this.filesListWidth < 768) {
134137
return 1
135138
}
136-
if (this.clientWidth < 768) {
139+
if (this.filesListWidth < 1024) {
137140
return 2
138141
}
139142
return 3

apps/files/src/components/FilesListVirtual.vue

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<FileEntry :active="active"
3737
:index="index"
3838
:is-size-available="isSizeAvailable"
39+
:files-list-width="filesListWidth"
3940
:nodes="nodes"
4041
:source="item" />
4142
</template>
@@ -48,12 +49,17 @@
4849
</caption>
4950

5051
<!-- Thead-->
51-
<FilesListHeader :is-size-available="isSizeAvailable" :nodes="nodes" />
52+
<FilesListHeader :files-list-width="filesListWidth"
53+
:is-size-available="isSizeAvailable"
54+
:nodes="nodes" />
5255
</template>
5356

5457
<template #after>
5558
<!-- Tfoot-->
56-
<FilesListFooter :is-size-available="isSizeAvailable" :nodes="nodes" :summary="summary" />
59+
<FilesListFooter :files-list-width="filesListWidth"
60+
:is-size-available="isSizeAvailable"
61+
:nodes="nodes"
62+
:summary="summary" />
5763
</template>
5864
</RecycleScroller>
5965
</template>
@@ -66,6 +72,7 @@ import Vue from 'vue'
6672
import FileEntry from './FileEntry.vue'
6773
import FilesListFooter from './FilesListFooter.vue'
6874
import FilesListHeader from './FilesListHeader.vue'
75+
import filesListWidthMixin from '../mixins/filesListWidth.ts'
6976
7077
export default Vue.extend({
7178
name: 'FilesListVirtual',
@@ -77,6 +84,10 @@ export default Vue.extend({
7784
FilesListFooter,
7885
},
7986
87+
mixins: [
88+
filesListWidthMixin,
89+
],
90+
8091
props: {
8192
currentView: {
8293
type: Object,
@@ -111,6 +122,10 @@ export default Vue.extend({
111122
return translate('files', '{summaryFile} and {summaryFolder}', this)
112123
},
113124
isSizeAvailable() {
125+
// Hide size column on narrow screens
126+
if (this.filesListWidth < 768) {
127+
return false
128+
}
114129
return this.nodes.some(node => node.attributes.size !== undefined)
115130
},
116131
},
@@ -318,22 +333,6 @@ export default Vue.extend({
318333
.files-list__row-column-custom {
319334
width: calc(var(--row-height) * 2);
320335
}
321-
322-
@media (max-width: 768px) {
323-
// Hide any column after the size menu on mobile
324-
.files-list__row-size ~ td,
325-
.files-list__row-size ~ th {
326-
display: none;
327-
}
328-
}
329-
330-
@media (max-width: 480px) {
331-
// Hide any column after the actions menu on short mobile
332-
.files-list__row-actions ~ td,
333-
.files-list__row-actions ~ th {
334-
display: none;
335-
}
336-
}
337336
}
338337
}
339338
</style>
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ import Vue from 'vue'
2525
export default Vue.extend({
2626
data() {
2727
return {
28-
clientWidth: null as number | null,
28+
filesListWidth: null as number | null,
2929
}
3030
},
3131
created() {
32-
window.addEventListener('resize', this.handleWindowResize)
33-
this.handleWindowResize()
32+
const fileListEl = document.querySelector('#app-content-vue')
33+
this.$resizeObserver = new ResizeObserver((entries) => {
34+
if (entries.length > 0 && entries[0].target === fileListEl) {
35+
this.filesListWidth = entries[0].contentRect.width
36+
}
37+
})
38+
this.$resizeObserver.observe(fileListEl as Element)
3439
},
3540
beforeDestroy() {
36-
window.removeEventListener('resize', this.handleWindowResize)
37-
},
38-
methods: {
39-
handleWindowResize() {
40-
this.clientWidth = document.documentElement.clientWidth
41-
},
41+
this.$resizeObserver.disconnect()
4242
},
4343
})

0 commit comments

Comments
 (0)