Skip to content

Commit fdbff17

Browse files
feat: update transitions (#143)
Co-authored-by: Dung Le <[email protected]>
1 parent dfc040b commit fdbff17

File tree

14 files changed

+354
-137
lines changed

14 files changed

+354
-137
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {
6-
"serve": "vite --host 0.0.0.0",
6+
"dev": "vite --host 0.0.0.0",
77
"build": "vue-tsc --noEmit && vite build",
88
"preview": "vite preview",
99
"store": "node tools/store/index"

src/App.vue

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
<template>
22
<el-config-provider :zIndex="9999">
3-
<AuthLayout v-if="isAuthLayout" />
4-
<DefaultLayout v-else />
3+
<component :is="isAuthLayout ? 'AuthLayout' : 'DefaultLayout'" v-if="isAppReady" />
54
</el-config-provider>
65
</template>
76

87
<script lang="ts">
9-
import { defineComponent, inject, computed } from 'vue'
108
import { ElConfigProvider } from 'element-plus'
11-
import DefaultLayout from './layouts/default-layout.vue'
129
import AuthLayout from 'layouts/auth-layout.vue'
13-
import { useRoute } from 'vue-router'
10+
import { computed, defineComponent, inject, nextTick, onMounted, ref } from 'vue'
11+
import { useRoute, useRouter } from 'vue-router'
12+
import DefaultLayout from './layouts/default-layout.vue'
1413
1514
export default defineComponent({
1615
components: {
@@ -22,21 +21,33 @@ export default defineComponent({
2221
2322
setup() {
2423
const $message = inject<IMessage>('$message')
25-
const router = useRoute()
26-
const isAuthLayout = computed(() => !router.meta?.requiresAuth)
27-
const initialize = () => {
28-
return Promise.resolve()
29-
}
30-
initialize().catch((error: Error) => {
31-
$message?.error(`Couldn't initialize the system with error: ${error.message}`)
24+
const route = useRoute()
25+
const router = useRouter()
26+
27+
const isAppReady = ref(false)
28+
29+
const isAuthLayout = computed(() => !route.meta?.requiresAuth)
30+
31+
onMounted(async () => {
32+
try {
33+
await router.isReady()
34+
35+
await nextTick()
36+
setTimeout(() => {
37+
isAppReady.value = true
38+
}, 200)
39+
} catch (error: unknown) {
40+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'
41+
$message?.error(`Couldn't initialize the system with error: ${errorMessage}`)
42+
}
3243
})
3344
34-
return { zIndex: 3000, size: 'small', isAuthLayout }
45+
return {
46+
zIndex: 3000,
47+
size: 'small',
48+
isAuthLayout,
49+
isAppReady,
50+
}
3551
},
3652
})
3753
</script>
38-
<style>
39-
#global-loading {
40-
z-index: 120000;
41-
}
42-
</style>

src/assets/css/transitions.css

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/* Global Page Transitions for Serene Admin */
2+
3+
/* Fade transitions */
4+
.fade-enter-active,
5+
.fade-leave-active {
6+
transition: opacity 0.3s ease;
7+
}
8+
9+
.fade-enter-from,
10+
.fade-leave-to {
11+
opacity: 0;
12+
}
13+
14+
/* Slide transitions */
15+
.slide-left-enter-active,
16+
.slide-left-leave-active {
17+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
18+
}
19+
20+
.slide-left-enter-from {
21+
opacity: 0;
22+
transform: translateX(20px);
23+
}
24+
25+
.slide-left-leave-to {
26+
opacity: 0;
27+
transform: translateX(-20px);
28+
}
29+
30+
/* Slide up transitions */
31+
.slide-up-enter-active,
32+
.slide-up-leave-active {
33+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
34+
}
35+
36+
.slide-up-enter-from {
37+
opacity: 0;
38+
transform: translateY(20px);
39+
}
40+
41+
.slide-up-leave-to {
42+
opacity: 0;
43+
transform: translateY(-20px);
44+
}
45+
46+
/* Scale transitions */
47+
.scale-enter-active,
48+
.scale-leave-active {
49+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
50+
}
51+
52+
.scale-enter-from {
53+
opacity: 0;
54+
transform: scale(0.95);
55+
}
56+
57+
.scale-leave-to {
58+
opacity: 0;
59+
transform: scale(1.05);
60+
}
61+
62+
/* Bounce transition for important elements */
63+
.bounce-enter-active {
64+
animation: bounce-in 0.5s;
65+
}
66+
67+
.bounce-leave-active {
68+
animation: bounce-in 0.5s reverse;
69+
}
70+
71+
@keyframes bounce-in {
72+
0% {
73+
transform: scale(0);
74+
opacity: 0;
75+
}
76+
50% {
77+
transform: scale(1.05);
78+
opacity: 0.8;
79+
}
80+
100% {
81+
transform: scale(1);
82+
opacity: 1;
83+
}
84+
}
85+
86+
/* Smooth modal transitions */
87+
.modal-enter-active,
88+
.modal-leave-active {
89+
transition: all 0.25s ease;
90+
}
91+
92+
.modal-enter-from {
93+
opacity: 0;
94+
transform: scale(1.1);
95+
}
96+
97+
.modal-leave-to {
98+
opacity: 0;
99+
transform: scale(0.9);
100+
}
101+
102+
/* List transitions */
103+
.list-enter-active,
104+
.list-leave-active {
105+
transition: all 0.5s ease;
106+
}
107+
108+
.list-enter-from,
109+
.list-leave-to {
110+
opacity: 0;
111+
transform: translateX(30px);
112+
}
113+
114+
/* Staggered list transitions */
115+
.list-move,
116+
.list-enter-active,
117+
.list-leave-active {
118+
transition: all 0.5s ease;
119+
}
120+
121+
.list-enter-from,
122+
.list-leave-to {
123+
opacity: 0;
124+
transform: translateX(30px);
125+
}
126+
127+
.list-leave-active {
128+
position: absolute;
129+
}
130+
131+
/* Page transition styles */
132+
.page-transition-enter-active,
133+
.page-transition-leave-active {
134+
transition: all 0.2s ease-in-out;
135+
}
136+
137+
.page-transition-enter-from {
138+
opacity: 0;
139+
transform: translateX(20px);
140+
}
141+
142+
.page-transition-leave-to {
143+
opacity: 0;
144+
transform: translateX(-20px);
145+
}
146+
147+
.page-transition-enter-to,
148+
.page-transition-leave-from {
149+
opacity: 1;
150+
transform: translateX(0);
151+
}
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
11
<template>
2-
<router-view></router-view>
2+
<router-view v-slot="{ Component, route }">
3+
<transition name="component-transition" mode="out-in">
4+
<component :is="Component" :key="route.fullPath" />
5+
</transition>
6+
</router-view>
37
</template>
8+
9+
<style scoped>
10+
/* Component transition styles */
11+
.component-transition-enter-active,
12+
.component-transition-leave-active {
13+
transition: all 0.25s ease-in-out;
14+
}
15+
16+
.component-transition-enter-from {
17+
opacity: 0;
18+
transform: translateY(15px);
19+
}
20+
21+
.component-transition-leave-to {
22+
opacity: 0;
23+
transform: translateY(-15px);
24+
}
25+
26+
.component-transition-enter-to,
27+
.component-transition-leave-from {
28+
opacity: 1;
29+
transform: translateY(0);
30+
}
31+
</style>

src/components/Footer/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="flex flex-wrap items-center md:justify-between w-full">
2+
<div class="flex flex-wrap items-center md:justify-between w-full p-5">
33
<div class="xl:flex-6 xl:max-w-1/2 mx-auto md:mx-0">
44
<div class="text-center lg:text-left text-muted">
55
© 2022
@@ -51,9 +51,9 @@
5151
</template>
5252

5353
<script lang="ts">
54-
import { defineComponent } from 'vue'
5554
import { Shop } from '@element-plus/icons-vue'
5655
import { MenuIcon, XIcon } from '@heroicons/vue/outline'
56+
import { defineComponent } from 'vue'
5757
5858
export default defineComponent({
5959
name: 'Footer',

src/index.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/* Import global transitions */
2+
@import './assets/css/transitions.css';
3+
14
@tailwind base;
25
@tailwind components;
36
@tailwind utilities;
@@ -7,3 +10,25 @@
710
font-family: 'Open Sans', sans-serif;
811
}
912
}
13+
14+
@layer components {
15+
/* Reset margins on popper elements to prevent warnings */
16+
.el-popper,
17+
.el-tooltip__popper,
18+
.el-dropdown__popper,
19+
.el-select-dropdown,
20+
.el-picker-panel,
21+
.el-autocomplete-suggestion {
22+
margin: 0 !important;
23+
}
24+
25+
/* Use padding instead of margin for proper spacing */
26+
.el-popper.is-pure {
27+
padding: 0;
28+
}
29+
30+
/* Ensure proper spacing using transforms/positioning instead of margins */
31+
.el-popper[data-popper-placement] {
32+
margin: 0 !important;
33+
}
34+
}

src/layouts/auth-layout.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
</div>
1010

1111
<div class="relative w-full">
12-
<router-view v-slot="{ Component }">
13-
<component :is="Component" />
12+
<router-view v-slot="{ Component, route }">
13+
<transition name="fade" mode="out-in">
14+
<component :is="Component" :key="route.fullPath" />
15+
</transition>
1416
</router-view>
1517
</div>
1618
</div>
@@ -23,8 +25,8 @@
2325
</template>
2426

2527
<script lang="ts">
26-
import { defineComponent, computed } from 'vue'
2728
import useStore from 'store'
29+
import { computed, defineComponent } from 'vue'
2830
2931
export default defineComponent({
3032
setup() {

src/layouts/default-layout.vue

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,21 @@
3939
</div>
4040
</div>
4141
</div>
42-
43-
<router-view v-slot="{ Component }">
44-
<component
45-
:is="Component"
46-
:class="{ 'py-1.25 px-4 md:px-7.5 lg:px-6.2': !route.meta.isFullWidthLayout }"
47-
/>
48-
</router-view>
49-
50-
<div class="w-full py-8 mx-auto px-4 md:px-7.5 lg:px-7.15">
51-
<Footer />
42+
<div class="p-3.75 md:p-7.25 min-h-[calc(100vh_-_216px)]">
43+
<router-view v-slot="{ Component }">
44+
<component :is="Component"></component>
45+
</router-view>
5246
</div>
47+
<Footer />
5348
</div>
5449
</div>
5550
</div>
5651
</template>
5752

5853
<script lang="ts">
59-
import { defineComponent, computed } from 'vue'
60-
import useStore from 'store'
6154
import { HomeFilled } from '@element-plus/icons-vue'
55+
import useStore from 'store'
56+
import { computed, defineComponent } from 'vue'
6257
import { useRoute } from 'vue-router'
6358
6459
export default defineComponent({
@@ -86,9 +81,6 @@ export default defineComponent({
8681
</script>
8782

8883
<style scoped>
89-
.main-content {
90-
@apply transition-all duration-300;
91-
}
9284
@media screen and (max-width: 1023px) {
9385
.main-content {
9486
margin-left: 0 !important;

src/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import vueEmitter from 'core/emitter'
2-
import { createApp, h } from 'vue'
3-
import { createPinia } from 'pinia'
42
import ElementPlus from 'element-plus'
3+
import { createPinia } from 'pinia'
4+
import { createApp, h } from 'vue'
5+
import VueSweetAlert2 from 'vue-sweetalert2'
56
import App from './App.vue'
67
import AppComponents from './components'
7-
import VueSweetAlert2 from 'vue-sweetalert2'
88

99
import { library } from '@fortawesome/fontawesome-svg-core'
10-
import { fas } from '@fortawesome/free-solid-svg-icons'
1110
import { fab } from '@fortawesome/free-brands-svg-icons'
11+
import { fas } from '@fortawesome/free-solid-svg-icons'
1212
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
1313

1414
import 'sweetalert2/dist/sweetalert2.min.css'

0 commit comments

Comments
 (0)