diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css index d527986..fbc1d1d 100644 --- a/frontend/src/assets/main.css +++ b/frontend/src/assets/main.css @@ -57,6 +57,66 @@ align-self: stretch; } } +/* Directory navigation slide transitions */ +.transition-wrapper { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; +} + +.explorer-content { + grid-area: 1 / 1; +} + +.slide-forward-enter-active, +.slide-backward-enter-active { + z-index: 2; +} + +.slide-forward-leave-active, +.slide-backward-leave-active { + z-index: 1; +} + +.slide-forward-enter-active, +.slide-forward-leave-active, +.slide-backward-enter-active, +.slide-backward-leave-active { + transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1); +} + +.slide-forward-enter-from { + transform: translate3d(100%, 0, 0); +} + +.slide-forward-enter-to { + transform: translate3d(0, 0, 0); +} + +.slide-forward-leave-from { + transform: translate3d(0, 0, 0); +} + +.slide-forward-leave-to { + transform: translate3d(-100%, 0, 0); +} + +.slide-backward-enter-from { + transform: translate3d(-100%, 0, 0); +} + +.slide-backward-enter-to { + transform: translate3d(0, 0, 0); +} + +.slide-backward-leave-from { + transform: translate3d(0, 0, 0); +} + +.slide-backward-leave-to { + transform: translate3d(100%, 0, 0); +} + @media print { :root { --primary-color: black; @@ -206,6 +266,8 @@ main { min-height: 0; /* Allow flex child to shrink below content size */ padding-bottom: 3em; /* convenience space on the bottom */ overflow-y: scroll; + overflow-x: hidden; + position: relative; text-align: center; } diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index fdffbef..28d3c34 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -1,6 +1,12 @@ +import { useMainStore } from '@/stores/main' import ExplorerView from '@/views/ExplorerView.vue' import { createRouter, createWebHashHistory } from 'vue-router' +function getPathDepth(path: string): number { + const pathPart = decodeURIComponent(path).split('//')[0] ?? '' + return pathPart.split('/').filter(Boolean).length +} + const router = createRouter({ history: createWebHashHistory(import.meta.env.BASE_URL), routes: [ @@ -12,4 +18,17 @@ const router = createRouter({ ] }) +router.beforeEach((to, from) => { + const store = useMainStore() + const toDepth = getPathDepth(to.path) + const fromDepth = getPathDepth(from.path) + if (toDepth > fromDepth) { + store.transitionDirection = 'forward' + } else if (toDepth < fromDepth) { + store.transitionDirection = 'backward' + } else { + store.transitionDirection = 'none' + } +}) + export default router diff --git a/frontend/src/stores/main.ts b/frontend/src/stores/main.ts index c0ee168..91efd14 100644 --- a/frontend/src/stores/main.ts +++ b/frontend/src/stores/main.ts @@ -98,6 +98,7 @@ export const useMainStore = defineStore('main', { privileged: false as boolean, isLoggedIn: false as boolean }, + transitionDirection: 'none' as 'forward' | 'backward' | 'none', space: { disk: 0, free: 0, diff --git a/frontend/src/views/ExplorerView.vue b/frontend/src/views/ExplorerView.vue index c8e9dd7..f663b05 100644 --- a/frontend/src/views/ExplorerView.vue +++ b/frontend/src/views/ExplorerView.vue @@ -1,24 +1,32 @@