Skip to content

Instantly share code, notes, and snippets.

@paularmstrong
Last active March 26, 2024 04:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paularmstrong/55dba2236340e8c7202cfca64f1a8ad6 to your computer and use it in GitHub Desktop.
Save paularmstrong/55dba2236340e8c7202cfca64f1a8ad6 to your computer and use it in GitHub Desktop.
SolidJS with Solid Router View Transition provider.
import { useBeforeLeave, useIsRouting } from '@solidjs/router';
import type { ParentProps } from 'solid-js';
/**
* Usage:
*
* Wrap your application, from within the <Router> with the TransitionProvider:
*
* ```ts
* return (
* <Router>
* <TransitionProvider>
* ...rest of app
* </TransitionProvider>
* </Router>
* );
* ```
*/
export function TransitionProvider(props: ParentProps) {
const routing = useIsRouting();
useBeforeLeave((e) => {
/**
* If ViewTransitions are not supported or we're staying on the same page,
* do nothing and continue on with the default routing behavior
*/
if (!('startViewTransition' in document) || e.from.pathname === e.to) {
return;
}
// Stop the default routing behavior
e.preventDefault();
/**
* Start the new transition. This takes a snapshot of the page.
*/
// @ts-expect-error new/experimental
const transition = document.startViewTransition(() => {
// Allow Solid Router to continue
e.retry(true);
/**
* Wait to resolve until the router is done routing.
* This allows all routing network requests to finish, including
* required scripts and `load` calls bound to the Route.
*/
return new Promise<void>((resolve) => {
function isDone() {
if (!routing()) {
resolve();
return;
}
setTimeout(isDone, 60);
}
setTimeout(isDone, 60);
});
});
const isSmallScreen = window.innerWidth <= 768;
transition.ready.then(() => {
/**
* On small screens, animate the new view in from the right
* As well, or if not on a small screen, fad the new view in over top
*/
document.documentElement.animate(
[
{
transform: isSmallScreen ? 'translateX(50%)' : undefined,
opacity: 0,
},
{
transform: isSmallScreen ? 'translateX(0)' : undefined,
opacity: 1,
},
],
{
duration: 150,
easing: 'ease-in',
// Specify which pseudo-element to animate
pseudoElement: '::view-transition-new(root)',
},
);
});
});
return props.children;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment