diff --git a/examples/react/view-transitions/src/routes/posts.route.tsx b/examples/react/view-transitions/src/routes/posts.route.tsx index 88296c3c54a..983d2943907 100644 --- a/examples/react/view-transitions/src/routes/posts.route.tsx +++ b/examples/react/view-transitions/src/routes/posts.route.tsx @@ -1,6 +1,10 @@ -import { createFileRoute } from '@tanstack/react-router' +import { + Link, + Outlet, + createFileRoute, + useRouter, +} from '@tanstack/react-router' import * as React from 'react' -import { Link, Outlet } from '@tanstack/react-router' import { fetchPosts } from '../posts' export const Route = createFileRoute('/posts')({ @@ -10,6 +14,7 @@ export const Route = createFileRoute('/posts')({ function PostsLayoutComponent() { const posts = Route.useLoaderData() + const router = useRouter() return (
@@ -25,8 +30,30 @@ function PostsLayoutComponent() { }} className="block py-1 text-blue-600 hover:opacity-75" activeProps={{ className: 'font-bold underline' }} - // see styles.css for 'warp' transition - viewTransition={{ types: ['warp'] }} + // see styles.css for 'warp' and 'warp-backwards' transition + viewTransition={{ + types: ({ fromLocation, toLocation }) => { + const fromRoute = router + .matchRoutes(fromLocation?.pathname ?? '/') + .find((entry) => entry.routeId === '/posts/$postId') + const toRoute = router + .matchRoutes(toLocation?.pathname ?? '/') + .find((entry) => entry.routeId === '/posts/$postId') + + const fromIndex = Number(fromRoute?.params.postId) + const toIndex = Number(toRoute?.params.postId) + + if ( + Number.isNaN(fromIndex) || + Number.isNaN(toIndex) || + fromIndex === toIndex + ) { + return false // no transition + } + + return fromIndex > toIndex ? ['warp-backwards'] : ['warp'] + }, + }} >
{post.title.substring(0, 20)}
diff --git a/examples/react/view-transitions/src/styles.css b/examples/react/view-transitions/src/styles.css index 818667133d4..172cf34be99 100644 --- a/examples/react/view-transitions/src/styles.css +++ b/examples/react/view-transitions/src/styles.css @@ -87,6 +87,16 @@ html:active-view-transition-type(warp) { } } +html:active-view-transition-type(warp-backwards) { + &::view-transition-old(post) { + animation: 400ms ease-out both warp-out-backwards; + } + + &::view-transition-new(post) { + animation: 400ms ease-out both warp-in-backwards; + } +} + @keyframes warp-out { from { opacity: 1; @@ -112,3 +122,29 @@ html:active-view-transition-type(warp) { transform: scale(1) rotate(0deg); } } + +@keyframes warp-in-backwards { + from { + opacity: 0; + filter: blur(15px) brightness(1.8); + transform: scale(0.9) rotate(45deg); + } + to { + opacity: 1; + filter: blur(0) brightness(1); + transform: scale(1) rotate(0deg); + } +} + +@keyframes warp-out-backwards { + from { + opacity: 1; + filter: blur(0) brightness(1); + transform: scale(1) rotate(0deg); + } + to { + opacity: 0; + filter: blur(15px) brightness(1.8); + transform: scale(1.1) rotate(-90deg); + } +}