add route/component transition animation and an option to disable it

This commit is contained in:
Axolotle 2020-10-08 23:58:09 +02:00
parent 2b199b712f
commit 64c6aefe63
6 changed files with 119 additions and 16 deletions

View file

@ -1,20 +1,25 @@
<template>
<div id="app" class="container">
<!-- HEADER -->
<header>
<b-navbar>
<b-navbar-brand :to="{ name: 'home' }" exact exact-active-class="active">
<img alt="Yunohost logo" src="./assets/logo.png">
</b-navbar-brand>
<b-navbar-nav class="ml-auto">
<li class="nav-item">
<b-button href="/yunohost/sso"
<b-button
href="/yunohost/sso"
variant="primary" size="sm" block
>
{{ $t('user_interface_link') }} <icon iname="user" />
</b-button>
</li>
<li class="nav-item" v-show="connected">
<b-button @click.prevent="logout" to="/logout"
<b-button
@click.prevent="logout"
variant="outline-dark" block size="sm"
>
{{ $t('logout') }} <icon iname="sign-out" />
@ -24,12 +29,17 @@
</b-navbar>
</header>
<breadcrumb v-if="$route.meta.breadcrumb" />
<!-- MAIN -->
<breadcrumb />
<main id="main">
<router-view />
<transition v-if="transitions" :name="transitionName">
<router-view class="animated" />
</transition>
<router-view v-else class="static" />
</main>
<!-- FOOTER -->
<footer>
<nav>
<b-nav class="justify-content-center">
@ -70,8 +80,25 @@ import { mapGetters } from 'vuex'
export default {
name: 'App',
data () {
return {
transitionName: null
}
},
computed: {
...mapGetters(['connected', 'yunohost'])
...mapGetters(['connected', 'yunohost', 'transitions'])
},
watch: {
// Set the css class to animate the components transition
'$route' (to, from) {
if (!this.transitions) return
// Use the breadcrumb array length as a direction indicator
const toDepth = to.meta.breadcrumb.length
const fromDepth = from.meta.breadcrumb.length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
},
methods: {
@ -139,4 +166,30 @@ export default {
}
}
}
main {
position: relative;
// Routes transition
.animated {
transition: all .15s ease-in-out;
}
.slide-left-enter, .slide-right-leave-active {
position: absolute;
width: 100%;
top: 0;
transform: translate(100vw, 0);
}
.slide-left-leave-active, .slide-right-enter {
position: absolute;
width: 100%;
top: 0;
transform: translate(-100vw, 0);
}
// hack to hide last transition provoqued by the <router-view> element change
// while disabling the transitions in ToolWebAdmin
.static ~ .animated {
display: none;
}
}
</style>

View file

@ -1,14 +1,14 @@
<template>
<b-breadcrumb>
<b-breadcrumb v-if="breadcrumb && breadcrumb.length">
<b-breadcrumb-item to="/">
<span class="sr-only">{{ $t('home') }}</span>
<icon iname="home" />
</b-breadcrumb-item>
<b-breadcrumb-item
v-for="(route, index) in breadcrumb"
:key="index"
v-for="(route, index) in breadcrumb" :key="index"
:to="{name: route.name}"
:active="index == lastIndex ? true : false"
:active="index === lastIndex"
>
{{ route.text }}
</b-breadcrumb-item>
@ -18,11 +18,14 @@
<script>
export default {
name: 'Breadcrumb',
computed: {
params: function () {
return this.$route.params
},
breadcrumb: function () {
if (!this.$route.meta.breadcrumb) return null
return this.$route.meta.breadcrumb.map(({ name, trad, param }) => {
let text = ''
// if a traduction key string has been given and we also need to pass
@ -37,6 +40,7 @@ export default {
return { name, text }
})
},
lastIndex: function () {
return this.breadcrumb.length - 1
}

View file

@ -354,7 +354,8 @@
"cache": "Cache",
"cache_description": "Consider disabling the cache if you plan on working with the CLI while also navigating in this web-admin.",
"experimental": "Experimental mode",
"experimental_description": "Gives you access to experimental features. These are considered unstable and may break your system.<br> Enabled this only if you know what you are doing."
"experimental_description": "Gives you access to experimental features. These are considered unstable and may break your system.<br> Enabled this only if you know what you are doing.",
"transitions": "Page transition animations"
},
"tools_webadmin_settings": "Web-admin settings",
"udp": "UDP",

View file

@ -7,8 +7,20 @@ import { DomainList, DomainAdd, DomainInfo, DomainDns, DomainCert } from '@/view
import { ServiceList, ServiceInfo } from '@/views/service'
const routes = [
{ name: 'home', path: '/', component: Home },
{ name: 'login', path: '/login', component: Login, meta: { noAuth: true } },
{
name: 'home',
path: '/',
component: Home,
// Leave the empty breadcrumb as it is used by the animated transition to know which way to go
meta: { breadcrumb: [] }
},
{
name: 'login',
path: '/login',
component: Login,
meta: { noAuth: true, breadcrumb: [] }
},
/*
POST INSTALL
@ -17,6 +29,7 @@ const routes = [
name: 'post-install',
path: '/postinstall',
component: () => import(/* webpackChunkName: "views/postinstall" */ '@/views/PostInstall'),
// Leave the breadcrumb
meta: { noAuth: true }
},

View file

@ -12,6 +12,7 @@ export default {
locale: localStorage.getItem('locale'),
fallbackLocale: localStorage.getItem('fallbackLocale'),
cache: localStorage.getItem('cache') !== 'false',
transitions: localStorage.getItem('transitions') !== 'false',
experimental: localStorage.getItem('experimental') === 'true',
supportedLocales: supportedLocales
},
@ -32,6 +33,11 @@ export default {
state.cache = boolean
},
'SET_TRANSITIONS' (state, boolean) {
localStorage.setItem('transitions', boolean)
state.transitions = boolean
},
'SET_EXPERIMENTAL' (state, boolean) {
localStorage.setItem('experimental', boolean)
state.experimental = boolean
@ -61,6 +67,7 @@ export default {
locale: state => (state.locale),
fallbackLocale: state => (state.fallbackLocale),
cache: state => (state.cache),
transitions: state => (state.transitions),
experimental: state => state.experimental,
availableLocales: state => {

View file

@ -39,11 +39,22 @@
{{ $t('tools_webadmin.cache_description') }}
</template>
</b-form-group>
<hr>
<!-- EXPERIMENTAL MODE -->
<!-- TRANSITIONS -->
<b-form-group
label-cols="0" label-cols-lg="2"
:label="$t('tools_webadmin.transitions')" label-for="transitions" label-class="font-weight-bold"
>
<b-checkbox v-model="currentTransitions" id="transitions" switch>
{{ $t(currentTransitions ? 'enabled' : 'disabled') }}
</b-checkbox>
</b-form-group>
<hr>
<!-- EXPERIMENTAL MODE (dev environment only)-->
<b-form-group
v-if="isDev"
label-cols="0" label-cols-lg="2" label-class="font-weight-bold"
label-for="experimental"
>
@ -75,6 +86,7 @@ export default {
'locale',
'fallbackLocale',
'cache',
'transitions',
'experimental',
'availableLocales'
]),
@ -100,6 +112,19 @@ export default {
}
},
currentTransitions: {
get: function () { return this.transitions },
set: function (newValue) {
this.$store.commit('SET_TRANSITIONS', newValue)
}
},
// environment
isDev () {
return process.env.NODE_ENV === 'development'
},
// Only available in 'development' environment.
currentExperimental: {
get: function () { return this.experimental },
set: function (newValue) {