Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable4] Fix styling issues and make the FilePicker height fixed #972

Merged
merged 3 commits into from Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions l10n/messages.pot
Expand Up @@ -38,11 +38,11 @@ msgstr ""
msgid "Copy to {target}"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:249
#: lib/components/FilePicker/FilePicker.vue:250
msgid "Could not create the new folder"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:159
#: lib/components/FilePicker/FilePicker.vue:160
#: lib/components/FilePicker/FilePickerNavigation.vue:65
msgid "Favorites"
msgstr ""
Expand All @@ -51,11 +51,11 @@ msgstr ""
msgid "File name cannot be empty."
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:235
#: lib/components/FilePicker/FilePicker.vue:236
msgid "Files and folders you mark as favorite will show up here."
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:233
#: lib/components/FilePicker/FilePicker.vue:234
msgid "Files and folders you recently modified will show up here."
msgstr ""

Expand All @@ -75,7 +75,7 @@ msgstr ""
msgid "Name"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:159
#: lib/components/FilePicker/FilePicker.vue:160
#: lib/components/FilePicker/FilePickerNavigation.vue:61
msgid "Recent"
msgstr ""
Expand Down Expand Up @@ -106,6 +106,6 @@ msgstr ""
msgid "Unset"
msgstr ""

#: lib/components/FilePicker/FilePicker.vue:231
#: lib/components/FilePicker/FilePicker.vue:232
msgid "Upload some content or sync with your devices!"
msgstr ""
19 changes: 14 additions & 5 deletions lib/components/DialogBase.vue
Expand Up @@ -5,14 +5,14 @@
@close="handleClose">
<!-- The dialog name / header -->
<h2 class="dialog__name" v-text="name" />
<div class="dialog">
<div class="dialog" :class="dialogClasses">
<div ref="wrapper" :class="['dialog__wrapper', { 'dialog__wrapper--collapsed': isNavigationCollapsed }]">
<!-- When the navigation is collapsed (too small dialog) it is displayed above the main content, otherwise on the inline start -->
<nav v-if="hasNavigation" :class="['dialog__navigation', ...navigationClasses]">
<nav v-if="hasNavigation" class="dialog__navigation" :class="navigationClasses">
<slot name="navigation" :is-collapsed="isNavigationCollapsed" />
</nav>
<!-- Main dialog content -->
<div :class="['dialog__content', ...contentClasses]">
<div class="dialog__content" :class="contentClasses">
<slot>
<p>{{ props.message }}</p>
</slot>
Expand All @@ -32,10 +32,13 @@
</template>

<script setup lang="ts">
import type { IDialogButton } from './types'
import { NcModal } from '@nextcloud/vue'
import { computed, ref, useSlots } from 'vue'
import DialogButton, { type IDialogButton } from './DialogButton.vue'
import { useElementSize } from '@vueuse/core'
import { computed, ref, useSlots } from 'vue'
import DialogButton from './DialogButton.vue'
const props = withDefaults(defineProps<{
/** Name of the dialog (the heading) */
Expand Down Expand Up @@ -79,12 +82,18 @@ const props = withDefaults(defineProps<{
* @default []
*/
contentClasses?: string[]
/**
* Optionally pass additionaly classes which will be set on the dialog itself
* (the default `class` attribute will be set on the modal wrapper)
*/
dialogClasses?: string|Record<string, boolean>|(string|Record<string, boolean>)[]
}>(), {
additionalTrapElements: () => [],
buttons: () => [],
container: undefined,
message: '',
contentClasses: () => [],
dialogClasses: () => [],
navigationClasses: () => [],
size: 'small',
})
Expand Down
37 changes: 31 additions & 6 deletions lib/components/FilePicker/FileList.vue
@@ -1,5 +1,5 @@
<template>
<div class="file-picker__files">
<div class="file-picker__files" ref="fileContainer">
<table>
<thead>
<tr>
Expand Down Expand Up @@ -51,7 +51,7 @@
</thead>
<tbody>
<template v-if="loading">
<LoadingTableRow v-for="i in [1, 2, 3, 4]" :key="i" :show-checkbox="multiselect"/>
<LoadingTableRow v-for="index in skeletonNumber" :key="index" :show-checkbox="multiselect"/>
</template>
<template v-else>
<FileListRow v-for="file in sortedFiles"
Expand All @@ -76,7 +76,7 @@ import { getCanonicalLocale } from '@nextcloud/l10n'
import { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'
import { join } from 'path'
import { t } from '../../utils/l10n'
import { computed, ref, type Ref } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, ref, type Ref } from 'vue'
import IconSortAscending from 'vue-material-design-icons/MenuDown.vue'
import IconSortDescending from 'vue-material-design-icons/MenuUp.vue'
Expand Down Expand Up @@ -184,15 +184,40 @@ function onNodeSelected(file: Node) {
function onChangeDirectory(dir: Node) {
emit('update:path', join(props.path, dir.basename))
}
/**
* Number of loading skeletons to use to fill the filepicker
*/
const skeletonNumber = ref(4)
const fileContainer = ref<HTMLDivElement>()
{
const resize = () => nextTick(() => {
const nodes = fileContainer.value?.parentElement?.children || []
let height = fileContainer.value?.parentElement?.clientHeight || 450
for(let index = 0; index < nodes.length; index++) {
if (!fileContainer.value?.isSameNode(nodes[index])) {
height -= nodes[index].clientHeight
}
}
// container height - 50px table header / row height of 50px
skeletonNumber.value = Math.floor((height - 50) / 50)
})
onMounted(() => {
window.addEventListener('resize', resize)
resize()
})
onUnmounted(() => {
window.removeEventListener('resize', resize)
})
}
</script>

<style scoped lang="scss">
.file-picker {
&__files {
// ensure focus outlines are visible
padding: 2px;
padding-inline-start: 12px; // align with bread crumbs
min-height: calc(5 * var(--row-height, 50px)); // make file list not jumping when loading (1x header 4x loading placeholders)
margin: 2px;
margin-inline-start: 12px; // align with bread crumbs
overflow: scroll auto;
table {
Expand Down
21 changes: 15 additions & 6 deletions lib/components/FilePicker/FilePicker.vue
Expand Up @@ -126,8 +126,9 @@ const dialogProps = computed(() => ({
name: props.name,
buttons: dialogButtons.value,
size: 'large',
navigationClasses: ['file-picker__navigation'],
contentClasses: ['file-picker__content'],
dialogClasses: ['file-picker'],
navigationClasses: ['file-picker__navigation'],
}))
/**
Expand Down Expand Up @@ -258,11 +259,6 @@ export default {

<style scoped lang="scss">
.file-picker {
display: flex;
flex-direction: row;
min-height: 40vh;
gap: 22px;
&__view {
height: 50px; // align with breadcrumbs
display: flex;
Expand Down Expand Up @@ -291,8 +287,21 @@ export default {
}
}
:deep(.file-picker) {
// Dialog is max. 900px wide so the best looking height seems to be 800px
height: min(80vh, 800px);
}
@media (max-width: 512px) {
:deep(.file-picker) {
// below 512px the modal is fullscreen so we use 100% height - margin of heading (4px + 12px) - height of heading (default-clickable-area)
height: calc(100% - 16px - var(--default-clickable-area));
}
}
:deep(.file-picker__content) {
display: flex;
flex-direction: column;
overflow: hidden;
}
</style>
2 changes: 2 additions & 0 deletions lib/components/FilePicker/FilePickerNavigation.vue
Expand Up @@ -101,6 +101,8 @@ const updateFilterValue = (value: string) => emit('update:filterString', value)
min-width: 200px;
// ensure focus outline is visible
padding-block: 2px;
// make only the navigation scroll
overflow: auto;
:deep(.button-vue__wrapper) {
justify-content: start;
Expand Down