feat: use transition component everywhere
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
Dominik Pschenitschni 2022-11-12 19:24:02 +01:00
parent 631a19fa92
commit 8c44ed83e6
Signed by: dpschen
GPG Key ID: B257AC0149F43A77
30 changed files with 163 additions and 165 deletions

View File

@ -54,8 +54,8 @@
</p>
<modal
@close="() => showHowItWorks = false"
:enabled="showHowItWorks"
@close="() => showHowItWorks = false"
transition-name="fade"
:overflow="true"
variant="hint-modal"

View File

@ -39,7 +39,7 @@
</router-view>
<modal
v-if="currentModal"
:enabled="Boolean(currentModal)"
@close="closeModal()"
variant="scrolling"
class="task-detail-view-modal"
@ -237,6 +237,4 @@ labelStore.loadAllLabels()
.content-auth.z-unset {
z-index: unset;
}
@include modal-transition();
</style>

View File

@ -4,7 +4,7 @@
{{ date === null ? chooseDateLabel : formatDateShort(date) }}
</BaseButton>
<transition name="fade">
<CustomTransition name="fade">
<div v-if="show" class="datepicker-popup" ref="datepickerPopup">
<BaseButton
@ -84,7 +84,7 @@
{{ $t('misc.confirm') }}
</x-button>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -94,6 +94,7 @@ import flatPickr from 'vue-flatpickr-component'
import 'flatpickr/dist/flatpickr.css'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import {formatDate, formatDateShort} from '@/helpers/time/formatDate'
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'

View File

@ -36,7 +36,7 @@
</div>
</div>
<transition name="fade">
<CustomTransition name="fade">
<div class="search-results" :class="{'search-results-inline': inline}" v-if="searchResultsVisible">
<BaseButton
class="search-result-button is-fullwidth"
@ -78,8 +78,7 @@
</span>
</BaseButton>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -90,6 +89,7 @@ import {useI18n} from 'vue-i18n'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
function elementInResults(elem: string | any, label: string, query: string): boolean {
// Don't make create available if we have an exact match in our search results.

View File

@ -44,11 +44,11 @@
</div>
<slot name="header" />
</div>
<transition name="fade">
<CustomTransition name="fade">
<Message variant="warning" v-if="currentList.isArchived" class="mb-4">
{{ $t('list.archived') }}
</Message>
</transition>
</CustomTransition>
<slot v-if="loadedListId"/>
</div>
@ -60,6 +60,7 @@ import {useRoute} from 'vue-router'
import BaseButton from '@/components/base/BaseButton.vue'
import Message from '@/components/misc/message.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import ListModel from '@/models/list'
import ListService from '@/services/list'

View File

@ -14,11 +14,11 @@
{{ $t('filters.title') }}
</x-button>
<modal
@close="() => modalOpen = false"
:enabled="modalOpen"
transition-name="fade"
:overflow="true"
variant="hint-modal"
@close="() => modalOpen = false"
>
<filters
:has-title="true"

View File

@ -1,12 +1,12 @@
<template>
<transition name="flash-background">
<transition :name="name">
<slot />
</transition>
</template>
<script setup lang="ts">
defineProps<{
name: 'flash-background'
name: 'flash-background' | 'fade' | 'width' | 'modal'
}>()
</script>
@ -34,4 +34,34 @@ $flash-background-duration: 750ms;
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity $transition-duration;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.width-enter-active,
.width-leave-active {
transition: width $transition-duration;
}
.width-enter-from,
.width-leave-to {
width: 0;
}
.modal-enter,
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
transform: scale(0.9);
}
</style>

View File

@ -6,13 +6,13 @@
</BaseButton>
</slot>
<transition name="fade">
<CustomTransition name="fade">
<div class="dropdown-menu" v-if="open">
<div class="dropdown-content">
<slot :close="close"></slot>
</div>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -21,6 +21,7 @@ import {ref, type PropType} from 'vue'
import {onClickOutside} from '@vueuse/core'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import BaseButton from '@/components/base/BaseButton.vue'
defineProps({

View File

@ -1,7 +1,7 @@
<template>
<Teleport to="body">
<!-- FIXME: transition should not be included in the modal -->
<transition :name="transitionName">
<CustomTransition :name="transitionName" appear>
<section
v-if="enabled"
class="modal-mask"
@ -59,7 +59,7 @@
</div>
</div>
</section>
</transition>
</CustomTransition>
</Teleport>
</template>
@ -70,6 +70,7 @@ export default {
</script>
<script lang="ts" setup>
import CustomTransition from '@/components/misc/CustomTransition.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import {ref, useAttrs, watchEffect} from 'vue'
import {useScrollLock} from '@vueuse/core'

View File

@ -29,7 +29,7 @@
</card>
</no-auth-wrapper>
</section>
<transition name="fade">
<CustomTransition name="fade">
<section class="vikunja-loading" v-if="showLoading">
<Logo class="logo"/>
<p>
@ -37,7 +37,7 @@
{{ $t('ready.loading') }}
</p>
</section>
</transition>
</CustomTransition>
</template>
<script lang="ts" setup>
@ -47,6 +47,7 @@ import {useRouter, useRoute} from 'vue-router'
import Logo from '@/assets/logo.svg?component'
import ApiConfig from '@/components/misc/api-config.vue'
import Message from '@/components/misc/message.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
import {ERROR_NO_API_URL} from '@/helpers/checkAndSetApiUrl'

View File

@ -7,7 +7,7 @@
</BaseButton>
</div>
<transition name="fade">
<CustomTransition name="fade">
<div class="notifications-list" v-if="showNotifications" ref="popup">
<span class="head">{{ $t('notification.title') }}</span>
<div
@ -42,7 +42,7 @@
</span>
</p>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -52,6 +52,7 @@ import {useRouter} from 'vue-router'
import NotificationService from '@/services/notification'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import User from '@/components/misc/user.vue'
import { NOTIFICATION_NAMES as names, type INotification} from '@/modelTypes/INotification'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'

View File

@ -1,5 +1,5 @@
<template>
<modal v-if="active" @close="closeQuickActions" :overflow="isNewTaskCommand">
<modal :enabled="active" @close="closeQuickActions" :overflow="isNewTaskCommand">
<div class="card quick-actions">
<div class="action-input" :class="{'has-active-cmd': selectedCmd !== null}">
<div class="active-cmd tag" v-if="selectedCmd !== null">

View File

@ -169,21 +169,19 @@
</table>
</div>
<transition name="modal">
<modal
@close="showDeleteModal = false"
@submit="remove(listId)"
v-if="showDeleteModal"
>
<template #header>
<span>{{ $t('list.share.links.remove') }}</span>
</template>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="remove(listId)"
>
<template #header>
<span>{{ $t('list.share.links.remove') }}</span>
</template>
<template #text>
<p>{{ $t('list.share.links.removeText') }}</p>
</template>
</modal>
</transition>
<template #text>
<p>{{ $t('list.share.links.removeText') }}</p>
</template>
</modal>
</div>
</template>
@ -297,6 +295,4 @@ function getShareLink(hash: string, view: ListView = LIST_VIEWS.LIST) {
.sharables-list:not(.card-content) {
overflow-y: auto
}
@include modal-transition();
</style>

View File

@ -113,22 +113,20 @@
{{ $t('list.share.userTeam.notShared', {type: shareTypeNames}) }}
</nothing>
<transition name="modal">
<modal
@close="showDeleteModal = false"
@submit="deleteSharable()"
v-if="showDeleteModal"
>
<template #header>
<span>{{
$t('list.share.userTeam.removeHeader', {type: shareTypeName, sharable: sharableName})
}}</span>
</template>
<template #text>
<p>{{ $t('list.share.userTeam.removeText', {type: shareTypeName, sharable: sharableName}) }}</p>
</template>
</modal>
</transition>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="deleteSharable()"
>
<template #header>
<span>{{
$t('list.share.userTeam.removeHeader', {type: shareTypeName, sharable: sharableName})
}}</span>
</template>
<template #text>
<p>{{ $t('list.share.userTeam.removeText', {type: shareTypeName, sharable: sharableName}) }}</p>
</template>
</modal>
</div>
</template>
@ -381,8 +379,4 @@ async function find(query: string) {
return typeof sharables.value.find(s => s.id === m.id) === 'undefined'
})
}
</script>
<style lang="scss" scoped>
@include modal-transition();
</style>
</script>

View File

@ -3,7 +3,7 @@
@submit.prevent="createTask"
class="add-new-task"
>
<transition name="width">
<CustomTransition name="width">
<input
v-if="newTaskFieldActive"
v-model="newTaskTitle"
@ -13,7 +13,7 @@
ref="newTaskTitleField"
type="text"
/>
</transition>
</CustomTransition>
<x-button @click="showCreateTaskOrCreate" :shadow="false" icon="plus">
{{ $t('task.new') }}
</x-button>
@ -24,6 +24,8 @@
import {nextTick, ref} from 'vue'
import type {ITask} from '@/modelTypes/ITask'
import CustomTransition from '@/components/misc/CustomTransition.vue'
const emit = defineEmits<{
(e: 'create-task', title: string): Promise<ITask>
}>()

View File

@ -130,7 +130,7 @@
<!-- Delete modal -->
<modal
v-if="attachmentToDelete !== null"
:enabled="attachmentToDelete !== null"
@close="setAttachmentToDelete(null)"
@submit="deleteAttachment()"
>
@ -148,7 +148,7 @@
<!-- Attachment image modal -->
<modal
v-if="attachmentImageBlobUrl !== null"
:enabled="attachmentImageBlobUrl !== null"
@close="attachmentImageBlobUrl = null"
>
<img :src="attachmentImageBlobUrl" alt=""/>
@ -432,6 +432,4 @@ async function setCoverImage(attachment: IAttachment | null) {
border-radius: 4px;
font-size: .75rem;
}
@include modal-transition();
</style>

View File

@ -49,14 +49,12 @@ const label = computed(() => {
align-items: center;
padding-left: .5rem;
font-size: .9rem;
}
svg {
transform: rotate(-90deg);
transition: stroke-dashoffset 0.35s;
margin-right: .25rem;
}
circle {

View File

@ -43,7 +43,7 @@
>
· {{ $t('task.comment.edited', {date: formatDateSince(c.updated)}) }}
</span>
<transition name="fade">
<CustomTransition name="fade">
<span
class="is-inline-flex"
v-if="
@ -63,7 +63,7 @@
>
{{ $t('misc.saved') }}
</span>
</transition>
</CustomTransition>
</div>
<editor
:hasPreview="true"
@ -94,15 +94,15 @@
</figure>
<div class="media-content">
<div class="form">
<transition name="fade">
<CustomTransition name="fade">
<span
class="is-inline-flex"
v-if="taskCommentService.loading && creating"
class="is-inline-flex"
>
<span class="loader is-inline-block mr-2"></span>
{{ $t('task.comment.creating') }}
</span>
</transition>
</CustomTransition>
<div class="field">
<editor
:class="{
@ -132,22 +132,20 @@
</div>
</div>
<transition name="modal">
<modal
v-if="showDeleteModal"
@close="showDeleteModal = false"
@submit="() => deleteComment(commentToDelete)"
>
<template #header><span>{{ $t('task.comment.delete') }}</span></template>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="() => deleteComment(commentToDelete)"
>
<template #header><span>{{ $t('task.comment.delete') }}</span></template>
<template #text>
<p>
{{ $t('task.comment.deleteText1') }}<br/>
<strong class="has-text-white">{{ $t('misc.cannotBeUndone') }}</strong>
</p>
</template>
</modal>
</transition>
<template #text>
<p>
{{ $t('task.comment.deleteText1') }}<br/>
<strong class="has-text-white">{{ $t('misc.cannotBeUndone') }}</strong>
</p>
</template>
</modal>
</div>
</template>
@ -155,6 +153,7 @@
import {ref, reactive, computed, shallowReactive, watch, nextTick} from 'vue'
import {useI18n} from 'vue-i18n'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import Editor from '@/components/input/AsyncEditor'
import TaskCommentService from '@/services/taskComment'
@ -351,6 +350,4 @@ async function deleteComment(commentToDelete: ITaskComment) {
.media-content {
width: calc(100% - 48px - 2rem);
}
@include modal-transition();
</style>

View File

@ -5,7 +5,7 @@
<icon icon="align-left"/>
</span>
{{ $t('task.attributes.description') }}
<transition name="fade">
<CustomTransition name="fade">
<span class="is-small is-inline-flex" v-if="loading && saving">
<span class="loader is-inline-block mr-2"></span>
{{ $t('misc.saving') }}
@ -14,7 +14,7 @@
<icon icon="check"/>
{{ $t('misc.saved') }}
</span>
</transition>
</CustomTransition>
</h3>
<editor
:is-edit-enabled="canWrite"
@ -33,6 +33,7 @@
<script setup lang="ts">
import {ref,computed, watch, type PropType} from 'vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import Editor from '@/components/input/AsyncEditor'
import type {ITask} from '@/modelTypes/ITask'

View File

@ -17,7 +17,7 @@
>
{{ task.title.trim() }}
</h1>
<transition name="fade">
<CustomTransition name="fade">
<span
v-if="loading && saving"
class="is-inline-flex is-align-items-center"
@ -32,7 +32,7 @@
<icon icon="check" class="mr-2"/>
{{ $t('misc.saved') }}
</span>
</transition>
</CustomTransition>
</div>
</template>
@ -41,6 +41,7 @@ import {ref, computed, type PropType} from 'vue'
import {useRouter} from 'vue-router'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import ColorBubble from '@/components/misc/colorBubble.vue'
import Done from '@/components/misc/Done.vue'

View File

@ -5,8 +5,8 @@
<ButtonLink @click="() => visible = true">{{ $t('task.quickAddMagic.what') }}</ButtonLink>
</p>
<modal
@close="() => visible = false"
:enabled="visible"
@close="() => visible = false"
transition-name="fade"
:overflow="true"
variant="hint-modal"

View File

@ -14,7 +14,7 @@
<template v-if="editEnabled && showCreate">
<label class="label" key="label">
{{ $t('task.relation.new') }}
<transition name="fade">
<CustomTransition name="fade">
<span class="is-inline-flex" v-if="taskRelationService.loading">
<span class="loader is-inline-block mr-2"></span>
{{ $t('misc.saving') }}
@ -22,7 +22,7 @@
<span class="has-text-success" v-else-if="!taskRelationService.loading && saved">
{{ $t('misc.saved') }}
</span>
</transition>
</CustomTransition>
</label>
<div class="field" key="field-search">
<Multiselect
@ -133,7 +133,7 @@
</p>
<modal
v-if="relationToDelete !== undefined"
:enabled="relationToDelete !== undefined"
@close="relationToDelete = undefined"
@submit="removeTaskRelation()"
>
@ -163,6 +163,7 @@ import {RELATION_KINDS, RELATION_KIND, type IRelationKind} from '@/types/IRelati
import TaskRelationService from '@/services/taskRelation'
import TaskRelationModel from '@/models/taskRelation'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import Multiselect from '@/components/input/multiselect.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
@ -442,6 +443,4 @@ async function toggleTaskDone(task: ITask) {
padding: 0;
height: 18px; // The exact height of the checkbox in the container
}
@include modal-transition();
</style>

View File

@ -74,9 +74,9 @@
- {{ $t('task.detail.due', {at: formatDateSince(task.dueDate)}) }}
</time>
</BaseButton>
<transition name="fade">
<CustomTransition name="fade">
<defer-task v-if="+new Date(task.dueDate) > 0 && showDefer" v-model="task" ref="deferDueDate"/>
</transition>
</CustomTransition>
<priority-label :priority="task.priority" :done="task.done"/>
@ -140,6 +140,7 @@ import User from '@/components/misc/user.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
import ColorBubble from '@/components/misc/colorBubble.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import TaskService from '@/services/task'

View File

@ -16,8 +16,6 @@
// since $tablet is defined by bulma we can just define it after importing the utilities
$mobile: math.div($tablet, 2);
@import "mixins";
$family-sans-serif: 'Open Sans', Helvetica, Arial, sans-serif;
$vikunja-font: 'Quicksand', sans-serif;

View File

@ -1,12 +0,0 @@
/* Transitions */
@mixin modal-transition() {
.modal-enter,
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
transform: scale(0.9);
}
}

View File

@ -94,9 +94,9 @@
</div>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="deleteLabel(labelToDelete)"
v-if="showDeleteModal"
>
<template #header><span>{{ $t('task.label.delete.header') }}</span></template>

View File

@ -206,20 +206,18 @@
</div>
</div>
<transition name="modal">
<modal
v-if="showBucketDeleteModal"
@close="showBucketDeleteModal = false"
@submit="deleteBucket()"
>
<template #header><span>{{ $t('list.kanban.deleteHeaderBucket') }}</span></template>
<modal
:enabled="showBucketDeleteModal"
@close="showBucketDeleteModal = false"
@submit="deleteBucket()"
>
<template #header><span>{{ $t('list.kanban.deleteHeaderBucket') }}</span></template>
<template #text>
<p>{{ $t('list.kanban.deleteBucketText1') }}<br/>
{{ $t('list.kanban.deleteBucketText2') }}</p>
</template>
</modal>
</transition>
<template #text>
<p>{{ $t('list.kanban.deleteBucketText1') }}<br/>
{{ $t('list.kanban.deleteBucketText2') }}</p>
</template>
</modal>
</div>
</template>
</ListWrapper>
@ -792,6 +790,4 @@ $filter-container-height: '1rem - #{$switch-view-height}';
.move-card-leave-active {
display: none;
}
@include modal-transition();
</style>

View File

@ -43,7 +43,7 @@
:key="im.id"
:style="{'background-image': `url(${backgroundBlurHashes[im.id]})`}"
>
<transition name="fade">
<CustomTransition name="fade">
<BaseButton
v-if="backgroundThumbs[im.id]"
class="image-search__image-button"
@ -51,7 +51,7 @@
>
<img class="image-search__image" :src="backgroundThumbs[im.id]" alt="" />
</BaseButton>
</transition>
</CustomTransition>
<BaseButton
:href="`https://unsplash.com/@${im.info.author}`"
@ -102,7 +102,9 @@ import {ref, computed, shallowReactive} from 'vue'
import {useI18n} from 'vue-i18n'
import {useRoute, useRouter} from 'vue-router'
import debounce from 'lodash.debounce'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import {useBaseStore} from '@/stores/base'
import {useListStore} from '@/stores/lists'

View File

@ -430,9 +430,9 @@
</div>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="deleteTask()"
v-if="showDeleteModal"
>
<template #header><span>{{ $t('task.detail.delete.header') }}</span></template>
@ -1007,8 +1007,6 @@ line-height: 1;
padding-left: .25rem;
}
@include modal-transition();
.detail-content {
@media print {
width: 100% !important;

View File

@ -149,35 +149,32 @@
</modal>
<!-- Team delete modal -->
<transition name="modal">
<modal
@close="showDeleteModal = false"
@submit="deleteTeam()"
v-if="showDeleteModal"
>
<template #header><span>{{ $t('team.edit.delete.header') }}</span></template>
<modal
:enabled="showDeleteModal"
@close="showDeleteModal = false"
@submit="deleteTeam()"
>
<template #header><span>{{ $t('team.edit.delete.header') }}</span></template>
<template #text>
<p>{{ $t('team.edit.delete.text1') }}<br/>
{{ $t('team.edit.delete.text2') }}</p>
</template>
</modal>
<template #text>
<p>{{ $t('team.edit.delete.text1') }}<br/>
{{ $t('team.edit.delete.text2') }}</p>
</template>
</modal>
</transition>
<!-- User delete modal -->
<transition name="modal">
<modal
@close="showUserDeleteModal = false"
@submit="deleteMember()"
v-if="showUserDeleteModal"
>
<template #header><span>{{ $t('team.edit.deleteUser.header') }}</span></template>
<modal
:enabled="showUserDeleteModal"
@close="showUserDeleteModal = false"
@submit="deleteMember()"
>
<template #header><span>{{ $t('team.edit.deleteUser.header') }}</span></template>
<template #text>
<p>{{ $t('team.edit.deleteUser.text1') }}<br/>
{{ $t('team.edit.deleteUser.text2') }}</p>
</template>
</modal>
</transition>
<template #text>
<p>{{ $t('team.edit.deleteUser.text1') }}<br/>
{{ $t('team.edit.deleteUser.text2') }}</p>
</template>
</modal>
</div>
</template>
@ -339,6 +336,4 @@ async function leave() {
padding: 0;
}
}
@include modal-transition();
</style>