feat: add fade in for background images
continuous-integration/drone/pr Build is failing
Details
continuous-integration/drone/pr Build is failing
Details
This commit is contained in:
parent
af177071d6
commit
daf3212902
|
@ -1,13 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a @click="$store.commit('menuActive', false)" class="menu-hide-button" v-if="menuActive">
|
<a @click="$store.commit('menuActive', false)" class="menu-hide-button" v-if="menuActive">
|
||||||
<icon icon="times" />
|
<icon icon="times"/>
|
||||||
</a>
|
</a>
|
||||||
<div
|
<div
|
||||||
:class="{'has-background': background}"
|
:class="{'has-background': background || blurHash}"
|
||||||
:style="{'background-image': background && `url(${background})`}"
|
:style="{'background-image': blurHash && `url(${blurHash})`}"
|
||||||
class="app-container"
|
class="app-container"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
:class="{'is-visible': background}"
|
||||||
|
class="app-container-background"
|
||||||
|
:style="{'background-image': background && `url(${background})`}"></div>
|
||||||
<navigation/>
|
<navigation/>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
|
@ -24,7 +28,7 @@
|
||||||
|
|
||||||
<router-view name="popup" v-slot="{ Component }">
|
<router-view name="popup" v-slot="{ Component }">
|
||||||
<transition name="modal">
|
<transition name="modal">
|
||||||
<component :is="Component" />
|
<component :is="Component"/>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
|
|
||||||
|
@ -53,6 +57,7 @@ import QuickActions from '@/components/quick-actions/quick-actions.vue'
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const background = computed(() => store.state.background)
|
const background = computed(() => store.state.background)
|
||||||
|
const blurHash = computed(() => store.state.blurHash)
|
||||||
const menuActive = computed(() => store.state.menuActive)
|
const menuActive = computed(() => store.state.menuActive)
|
||||||
|
|
||||||
function showKeyboardShortcuts() {
|
function showKeyboardShortcuts() {
|
||||||
|
@ -77,7 +82,7 @@ watch(() => route.fullPath, () => {
|
||||||
'migrate.start',
|
'migrate.start',
|
||||||
'migrate.wunderlist',
|
'migrate.wunderlist',
|
||||||
'namespaces.index',
|
'namespaces.index',
|
||||||
].includes(route.name) ||
|
].includes(route.name) ||
|
||||||
route.name.startsWith('user.settings')
|
route.name.startsWith('user.settings')
|
||||||
) {
|
) {
|
||||||
store.dispatch(CURRENT_LIST, null)
|
store.dispatch(CURRENT_LIST, null)
|
||||||
|
@ -88,7 +93,7 @@ watch(() => route.fullPath, () => {
|
||||||
|
|
||||||
function useRenewTokenOnFocus() {
|
function useRenewTokenOnFocus() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const userInfo = computed(() => store.state.auth.info)
|
const userInfo = computed(() => store.state.auth.info)
|
||||||
const authenticated = computed(() => store.state.auth.authenticated)
|
const authenticated = computed(() => store.state.auth.authenticated)
|
||||||
|
|
||||||
|
@ -152,40 +157,41 @@ store.dispatch('labels/loadAllLabels')
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-container {
|
.app-container {
|
||||||
min-height: calc(100vh - 65px);
|
min-height: calc(100vh - 65px);
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
@media screen and (max-width: $tablet) {
|
||||||
padding-top: $navbar-height;
|
padding-top: $navbar-height;
|
||||||
}
|
|
||||||
|
|
||||||
.app-content {
|
|
||||||
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
|
||||||
margin-left: 0;
|
|
||||||
padding-top: 1.5rem;
|
|
||||||
min-height: calc(100vh - 4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-menu-enabled {
|
|
||||||
margin-left: $navbar-width;
|
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
|
||||||
min-width: 100%;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.task\.detail {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.app-content {
|
||||||
background: var(--white);
|
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
|
||||||
}
|
z-index: 10;
|
||||||
}
|
position: relative;
|
||||||
|
|
||||||
|
@media screen and (max-width: $tablet) {
|
||||||
|
margin-left: 0;
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
min-height: calc(100vh - 4rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-menu-enabled {
|
||||||
|
margin-left: $navbar-width;
|
||||||
|
|
||||||
|
@media screen and (max-width: $tablet) {
|
||||||
|
min-width: 100%;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.task\.detail {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-overlay {
|
.mobile-overlay {
|
||||||
|
@ -214,7 +220,7 @@ store.dispatch('labels/loadAllLabels')
|
||||||
|
|
||||||
color: var(--grey-500);
|
color: var(--grey-500);
|
||||||
transition: color $transition;
|
transition: color $transition;
|
||||||
|
|
||||||
@media screen and (max-width: $tablet) {
|
@media screen and (max-width: $tablet) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {createStore} from 'vuex'
|
||||||
import {getBlobFromBlurHash} from '../helpers/getBlobFromBlurHash'
|
import {getBlobFromBlurHash} from '../helpers/getBlobFromBlurHash'
|
||||||
import {
|
import {
|
||||||
BACKGROUND,
|
BACKGROUND,
|
||||||
|
BLUR_HASH,
|
||||||
CURRENT_LIST,
|
CURRENT_LIST,
|
||||||
HAS_TASKS,
|
HAS_TASKS,
|
||||||
KEYBOARD_SHORTCUTS_ACTIVE,
|
KEYBOARD_SHORTCUTS_ACTIVE,
|
||||||
|
@ -41,6 +42,7 @@ export const store = createStore({
|
||||||
// This is used to highlight the current list in menu for all list related views
|
// This is used to highlight the current list in menu for all list related views
|
||||||
currentList: {id: 0},
|
currentList: {id: 0},
|
||||||
background: '',
|
background: '',
|
||||||
|
blurHash: '',
|
||||||
hasTasks: false,
|
hasTasks: false,
|
||||||
menuActive: true,
|
menuActive: true,
|
||||||
keyboardShortcutsActive: false,
|
keyboardShortcutsActive: false,
|
||||||
|
@ -87,6 +89,9 @@ export const store = createStore({
|
||||||
[BACKGROUND](state, background) {
|
[BACKGROUND](state, background) {
|
||||||
state.background = background
|
state.background = background
|
||||||
},
|
},
|
||||||
|
[BLUR_HASH](state, blurHash) {
|
||||||
|
state.blurHash = blurHash
|
||||||
|
},
|
||||||
vikunjaReady(state, ready) {
|
vikunjaReady(state, ready) {
|
||||||
state.vikunjaReady = ready
|
state.vikunjaReady = ready
|
||||||
},
|
},
|
||||||
|
@ -97,6 +102,7 @@ export const store = createStore({
|
||||||
if (currentList === null) {
|
if (currentList === null) {
|
||||||
commit(CURRENT_LIST, {})
|
commit(CURRENT_LIST, {})
|
||||||
commit(BACKGROUND, null)
|
commit(BACKGROUND, null)
|
||||||
|
commit(BLUR_HASH, null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +136,8 @@ export const store = createStore({
|
||||||
if (currentList.backgroundInformation) {
|
if (currentList.backgroundInformation) {
|
||||||
try {
|
try {
|
||||||
const blurHash = await getBlobFromBlurHash(currentList.backgroundBlurHash)
|
const blurHash = await getBlobFromBlurHash(currentList.backgroundBlurHash)
|
||||||
if(blurHash) {
|
if (blurHash) {
|
||||||
commit(BACKGROUND, window.URL.createObjectURL(blurHash))
|
commit(BLUR_HASH, window.URL.createObjectURL(blurHash))
|
||||||
}
|
}
|
||||||
|
|
||||||
const listService = new ListService()
|
const listService = new ListService()
|
||||||
|
@ -145,6 +151,7 @@ export const store = createStore({
|
||||||
|
|
||||||
if (typeof currentList.backgroundInformation === 'undefined' || currentList.backgroundInformation === null) {
|
if (typeof currentList.backgroundInformation === 'undefined' || currentList.backgroundInformation === null) {
|
||||||
commit(BACKGROUND, null)
|
commit(BACKGROUND, null)
|
||||||
|
commit(BLUR_HASH, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
commit(CURRENT_LIST, currentList)
|
commit(CURRENT_LIST, currentList)
|
||||||
|
|
|
@ -7,6 +7,7 @@ export const MENU_ACTIVE = 'menuActive'
|
||||||
export const KEYBOARD_SHORTCUTS_ACTIVE = 'keyboardShortcutsActive'
|
export const KEYBOARD_SHORTCUTS_ACTIVE = 'keyboardShortcutsActive'
|
||||||
export const QUICK_ACTIONS_ACTIVE = 'quickActionsActive'
|
export const QUICK_ACTIONS_ACTIVE = 'quickActionsActive'
|
||||||
export const BACKGROUND = 'background'
|
export const BACKGROUND = 'background'
|
||||||
|
export const BLUR_HASH = 'blurHash'
|
||||||
|
|
||||||
export const CONFIG = 'config'
|
export const CONFIG = 'config'
|
||||||
export const AUTH = 'auth'
|
export const AUTH = 'auth'
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
.app-container.has-background,
|
.app-container.has-background,
|
||||||
.link-share-container.has-background {
|
.link-share-container.has-background {
|
||||||
background-position: center;
|
position: relative;
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-attachment: fixed;
|
|
||||||
min-height: 100vh;
|
|
||||||
|
|
||||||
// FIXME: move to pagination component
|
&, .app-container-background {
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-attachment: fixed;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: move to pagination component
|
||||||
.pagination-link:not(.is-current) {
|
.pagination-link:not(.is-current) {
|
||||||
background: var(--grey-100);
|
background: var(--grey-100);
|
||||||
}
|
}
|
||||||
|
@ -32,4 +36,18 @@
|
||||||
border-radius: $radius !important;
|
border-radius: $radius !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-container-background {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity $transition;
|
||||||
|
transition-delay: $transition-duration * 2; // To fake an appearing background
|
||||||
|
|
||||||
|
&.is-visible {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
// Computed property to let "listId" always have a value
|
// Computed property to let "listId" always have a value
|
||||||
listId() {
|
listId() {
|
||||||
return typeof this.$route.params.listId === 'undefined' ? 0 : this.$route.params.listId
|
return typeof this.$route.params.listId === 'undefined' ? 0 : parseInt(this.$route.params.listId)
|
||||||
},
|
},
|
||||||
background() {
|
background() {
|
||||||
return this.$store.state.background
|
return this.$store.state.background
|
||||||
|
@ -99,9 +99,11 @@ export default {
|
||||||
const listData = {id: parseInt(this.$route.params.listId)}
|
const listData = {id: parseInt(this.$route.params.listId)}
|
||||||
|
|
||||||
saveListToHistory(listData)
|
saveListToHistory(listData)
|
||||||
|
|
||||||
this.setTitle(this.currentList.id ? this.getListTitle(this.currentList) : '')
|
this.setTitle(this.currentList.id ? this.getListTitle(this.currentList) : '')
|
||||||
|
|
||||||
|
const listFromStore = this.$store.getters['lists/getListById'](this.listId)
|
||||||
|
await this.$store.dispatch(CURRENT_LIST, listFromStore)
|
||||||
|
|
||||||
// This invalidates the loaded list at the kanban board which lets it reload its content when
|
// This invalidates the loaded list at the kanban board which lets it reload its content when
|
||||||
// switched to it. This ensures updates done to tasks in the gantt or list views are consistently
|
// switched to it. This ensures updates done to tasks in the gantt or list views are consistently
|
||||||
// shown in all views while preventing reloads when closing a task popup.
|
// shown in all views while preventing reloads when closing a task popup.
|
||||||
|
@ -161,51 +163,51 @@ export default {
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.switch-view-container {
|
.switch-view-container {
|
||||||
@media screen and (max-width: $tablet) {
|
@media screen and (max-width: $tablet) {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.switch-view {
|
.switch-view {
|
||||||
background: var(--white);
|
background: var(--white);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
height: $switch-view-height;
|
height: $switch-view-height;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
padding: .25rem .5rem;
|
padding: .25rem .5rem;
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
|
|
||||||
transition: all 100ms;
|
transition: all 100ms;
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
margin-right: .5rem;
|
margin-right: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-active,
|
&.is-active,
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--switch-view-color);
|
color: var(--switch-view-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-active {
|
&.is-active {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
box-shadow: var(--shadow-xs);
|
box-shadow: var(--shadow-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-archived .notification.is-warning {
|
.is-archived .notification.is-warning {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Reference in New Issue