Last active
March 26, 2024 04:07
-
-
Save paularmstrong/55dba2236340e8c7202cfca64f1a8ad6 to your computer and use it in GitHub Desktop.
SolidJS with Solid Router View Transition provider.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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