Add support for View Transition API #46300
Replies: 34 comments 88 replies
-
Since viewTransition api is mostly for Multi pages Application (MPA), while nextjs is SPA-first oriented. You could implement such a thing by disabling all links or not using the Since this feature is also, not yet implemented by many vendors it will take a long time before any framework (next included) start looking to integrate it. |
Beta Was this translation helpful? Give feedback.
-
The View Transitions API is not intended for MPAs, but for SPAs.
The question is whether Next.js and React can and will support this. |
Beta Was this translation helpful? Give feedback.
-
Chrome 111 was released! |
Beta Was this translation helpful? Give feedback.
-
Would be nice to integrate it into the router. I assume it has to be achieved by flushSync where the new startViewTransition API can be called. |
Beta Was this translation helpful? Give feedback.
-
Some insight into how view transitions work: document.startViewTransition(async function viewTransitionCallback() {
// Change the DOM here
}); When you call Once the capture is complete, the The DOM must be updated to the 'new' state before the promise returned by Then, the browser captures the new state, and creates a transition between them. Between the browser calling The ideal pattern for a 'navigation' is this: await fetchEverythingNeededForTheNavigation();
document.startViewTransition(() => {
switchToTheNewView();
}); Svelte are looking to add a hook for this: onNavigate(async (navigation) => {
return new Promise((oldStateCaptureResolve) => {
document.startViewTransition(() => {
oldStateCaptureResolve();
await navigation.complete;
});
});
}); Where:
This lets view transitions fully integrate with the Svelte router. |
Beta Was this translation helpful? Give feedback.
-
Nuxt is also going to support it https://nuxt.com/docs/getting-started/transitions#view-transitions-api-experimental |
Beta Was this translation helpful? Give feedback.
-
There's no support for the new |
Beta Was this translation helpful? Give feedback.
-
I was playing around this on my own, and something like this will usually work for View Transitions: function useTransitionWithCompletion() {
const [isPending, startTransition] = useTransition();
const pendingPromise = useRef();
useLayoutEffect(() => {
if (!isPending && pendingPromise.current) {
pendingPromise.current.resolve();
pendingPromise.current = undefined;
}
}, [isPending]);
useLayoutEffect(() => () => {
if(pendingPromise.current) {
pendingPromise.current.reject();
pendingPromise.current = undefined;
}
}, [])
const startTransitionWithCompletion = (transition) => {
const promise = new Promise((resolve, reject) => {
pendingPromise.current = {resolve, reject};
});
startTransition(transition);
return promise;
};
return [isPending, startTransitionWithCompletion]
} Now you can use this hook instead of The main problem is of course that this fires for React transitions that have both completed or canceled. (Which may sometimes be OK) |
Beta Was this translation helpful? Give feedback.
-
I'm able to get this working in a decent state w/ the current version of Nextjs. The only issue I have left is the browser back/forward button doesn't trigger the animation - even though I do see The way I start the capture before the transition is by wrapping the import NextLink from 'next/link'
export function Link(props: AnchorHTMLAttributes<HTMLAnchorElement>) {
return <NextLink {...props} onClick={async () => {
await document.startViewTransition(()=> new Promise(res => setTimeout(res, 1)).finished
document.documentElement.classList.remove('back-transition')
}} />
} I have a hook that watches post route changes: 'use client'
import { usePathname } from 'next/navigation'
import { useEffect, useRef } from 'react'
export const useNavigationEvent = (onChange: (pathname: string, isBack: boolean) => void) => {
const pathname = usePathname()
const last = useRef(pathname)
useEffect(() => {
const isBack = last.current.startsWith(pathname)
if (last.current !== pathname) {
onChange(pathname, isBack)
}
last.current = pathname
}, [pathname, onChange])
} I use this to add "back-transition" if the route went back: |
Beta Was this translation helpful? Give feedback.
-
Maybe we can use the new template file for something like this? |
Beta Was this translation helpful? Give feedback.
-
This is what I came up with, seems to be working really well. import { useTransition, useEffect } from 'react';
import { useRouter as useNextRouter } from 'next/navigation';
function useRouter(): ReturnType<typeof useNextRouter> {
const [ , startTransition ] = useTransition();
const router = useNextRouter();
function safeViewTransition(fn: (...args: any) => any) {
if (document.startViewTransition !== undefined) {
document.startViewTransition(fn);
} else {
startTransition(fn);
}
}
return {
...router,
back: () => {
safeViewTransition(() => router.back());
},
forward: () => {
safeViewTransition(() => router.forward());
},
push: (...args: Parameters<typeof router.push>) => {
safeViewTransition(() => router.push(...args));
},
replace: (...args: Parameters<typeof router.replace>) => {
safeViewTransition(() => router.replace(...args));
}
};
} Adding similar logic to |
Beta Was this translation helpful? Give feedback.
-
It seems like they added some minimal description of how to do router events here. I guess we could use this to start the page transition? |
Beta Was this translation helpful? Give feedback.
-
I feel like I am so close now to having a working solution with the app router, just some edge cases to iron out. I have mixed in different approaches from all comments thus far and attempted to make things clean and tidy but alas it got messy. I will pick up again tomorrow and see what I can come up with chrome_Ea7EAgLSVd.mp4 |
Beta Was this translation helpful? Give feedback.
-
I wrote a custom hook for automatic view-transitions in NextJS that works without having to refactor the It uses the fact that the NextJS router calls |
Beta Was this translation helpful? Give feedback.
-
Some notes after playing with this a lot:
This was possible before with I think a possible good solution that can't be done in userland would be to make a configurable option that makes router-links start a view transition rather than a react |
Beta Was this translation helpful? Give feedback.
-
Overall, the answer is yes, we want to support the View Transitions API. I am not sure when, or exactly how, but I love how it's pushing the web forward. If you'd like to see support for this, please upvote this discussion 😄 |
Beta Was this translation helpful? Give feedback.
-
Using NextJS 13 with app-router, This is my solution: i created a hook: useAnimatedRouter
Now you have to add View Transitions API CSS code in the Global.css file.
|
Beta Was this translation helpful? Give feedback.
-
any update on this ? nuxt.js, astro and svelte already got their implementations of view transition API.. |
Beta Was this translation helpful? Give feedback.
-
Chrome for Developers introduces an example of View Transition API with Next.js. |
Beta Was this translation helpful? Give feedback.
-
Any update yet? I hope Nextjs14 has this at least experimentally |
Beta Was this translation helpful? Give feedback.
-
I've been playing around with Partial Pre-Rendering and Streaming responses with Suspense boundaries and think there will be issues around this with ViewTransitions. If we are streaming the response to the browser then that means the DOM / Load events are not fired until all the Suspense boundaries are resolved. In my testing at least, this means whilst we get a fast TTFB the actual full page loads are easily over 600ms for just a simple DB query to get a ViewCount for the current page (PlanetScale / Prisma). If pages take this long, won't we fall into a timeout on the Does anyone here have experience with how other frameworks do this with dynamic islands or streaming components from the server? |
Beta Was this translation helpful? Give feedback.
-
I am solely wanting to get client-side routing / soft navigation to work with NextJS App Router. The documentation says it's supported out of the box but I am not getting the intended not-full-page-refresh behaviour. Has anyone got this to work before trying to get the View Transitions to work? |
Beta Was this translation helpful? Give feedback.
-
Here's my implementation of View Transition api |
Beta Was this translation helpful? Give feedback.
-
@leerob any progress on this? Will the Transition Api be implemented in Next.js soon, so it won't be behind compared to others? This discussion has been open for some time after all. Thank you for the reply. |
Beta Was this translation helpful? Give feedback.
-
This is now available in Webkit/Safari technical preview 192: https://webkit.org/blog/15260/release-notes-for-safari-technology-preview-192/ This will be the way of doing performant 'use the platform' route transitions and it'd be great to start to see some first-party Next.js examples that don't rely on templates. |
Beta Was this translation helpful? Give feedback.
-
Hello, my name is Mike. I am looking for developers who have worked with the View Transitions API within Next.js. For my bachelor’s thesis, I need to reflect with external experts on the View Transitions API in Next.js. I have also created a small website in Next.js where I use the API. If there are developers who are willing to help me reflect on my project, let me know how I can get in touch. The reflection will involve answering a few questions. Hopefully, you can help me. |
Beta Was this translation helpful? Give feedback.
-
https://www.youtube.com/watch?v=eY6C_-aDdTo Does this make it more possible for NextJS App Router to natively adopt View Page Transitions? |
Beta Was this translation helpful? Give feedback.
-
I made a starter with a fully functional view transitions API (no extra library for transitions, no flushSync either).
|
Beta Was this translation helpful? Give feedback.
-
I've built a To start the transition, call the startViewTransition method and pass the imageElement. If the opened page has an image with the same src as imageElement, the transition will happen. In addition, it automatically stores image data in sessionStorage, which enables the display of view transitions during navigation using the browser's history (back/forward). Consider, you have a Link.tsx component like this import NextLink from 'next/link';
import React, { useCallback } from 'react';
import { useRouter } from 'next/router';
import { startViewTransition } from 'next-rich-view-transitions';
export function Link(props: React.ComponentProps<typeof NextLink>) {
const { href, as, replace, scroll } = props;
const router = useRouter();
const handleClick = useCallback(
(e: React.MouseEvent<HTMLAnchorElement>) => {
if (props.onClick) {
props.onClick(e);
}
if ('startViewTransition' in document) {
e.preventDefault();
const navigate = replace ? router.replace : router.push;
// Find an image that should start transitioning. Feel free to change that code.
const transitionImg = e.currentTarget.querySelector<HTMLImageElement>('.transitionable-img') || document.querySelector('#transition-img');
startViewTransition(transitionImg).then(() => {
navigate(as || href, as, { scroll: scroll ?? true });
});
}
},
[props.onClick, href, as, replace, scroll]
)
return (
<NextLink {...props} onClick={handleClick} />
)
} In handleClick, you await async method startViewTransition and navigate after that. |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
I would like to perform animation during transitions.
e.g. Transition as if opening a modal in a native app.
Describe the solution you'd like
Support the View Transitions API.
https://developer.chrome.com/docs/web-platform/view-transitions/
If we can pass the navfation in Next.js to
document.startViewTransition
, we should be able to achieve this.Describe alternatives you've considered
It would be difficult to support on its own.
Beta Was this translation helpful? Give feedback.
All reactions