Capítulo 16 de 24
This example wires the browser's native View Transitions API into route navigation, so switching between pages (e.g. Home and Posts) animates as a transition instead of an instant swap. TanStack Router exposes this per-Link/navigate via a viewTransition flag, or globally via defaultViewTransition on the router.
createFileRoute, routes generated into routeTree.gen.ts)@tanstack/react-router, @tanstack/router-plugin (drives file-based route generation), zod, @tanstack/react-router-devtoolssrc/main.tsx creates the router from the generated routeTree; src/routes/__root.tsx defines the root layout and nav links; src/routes/posts.$postId.tsx is a file-based dynamic route for an individual post, loaded via a loader.// src/routes/__root.tsx
<Link
to="/"
activeProps={{ className: 'font-bold' }}
activeOptions={{ exact: true }}
viewTransition
>
Home
</Link>{' '}
<Link
to="/posts"
activeProps={{ className: 'font-bold' }}
viewTransition
>
Posts
</Link>
The router also supports enabling this globally instead of per-link, including deriving transition "types" from the navigation direction:
// src/main.tsx (commented alternative shown in the example)
// defaultViewTransition: true
// OR
// defaultViewTransition: {
// types: ({ fromLocation, toLocation }) => {
// let direction = 'none'
// if (fromLocation) {
// const fromIndex = fromLocation.state.__TSR_index
// const toIndex = toLocation.state.__TSR_index
// direction = fromIndex > toIndex ? 'right' : 'left'
// }
// return [`slide-${direction}`]
// },
// },
The destination route itself is a plain file-based route with a loader and error/not-found components:
// src/routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => fetchPost(postId),
errorComponent: PostErrorComponent,
notFoundComponent: () => <p>Post not found</p>,
component: PostComponent,
})
viewTransition prop on Link (or navigate) opts a specific navigation into document.startViewTransition, while defaultViewTransition on createRouter can apply it to every navigation and optionally compute per-navigation transition types (e.g. slide direction) from fromLocation/toLocation history state.viewTransition on Link/navigate is opt-in per navigation; set defaultViewTransition: true on the router instead if you want it everywhere without annotating every link.defaultViewTransition.types as a function receiving { fromLocation, toLocation } lets you compute CSS view-transition types (e.g. slide-left vs slide-right) from navigation direction, using the router's internal __TSR_index history state to detect back/forward vs forward navigation.viewTransition with route-scoped CSS (view-transition-name) on the elements you want individually animated; the router only triggers the transition, the CSS still defines what animates.scrollRestoration: true with view transitions avoids a jarring scroll-jump mid-animation.