Skip to content

Instantly share code, notes, and snippets.

@jaksm
Created September 17, 2021 11:30
Show Gist options
  • Save jaksm/0156cef0113d59379aa677bb358e123f to your computer and use it in GitHub Desktop.
Save jaksm/0156cef0113d59379aa677bb358e123f to your computer and use it in GitHub Desktop.
Preact Animated Router (CSS only)
.page {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.out {
animation: out 450ms ease-out;
box-shadow: 84px -4px 114px 1px rgba(0, 0, 0, 0.1);
}
@keyframes out {
0% {
opacity: 1;
transform: translateX(0);
}
100% {
opacity: 0;
transform: translateX(-100vw);
}
}
.in {
animation: in 450ms ease-out;
box-shadow: -49px -13px 114px 1px rgba(0, 0, 0, 0.1);
}
@keyframes in {
0% {
opacity: 0;
transform: translateX(100vw);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
import { ComponentChildren, Fragment, h } from 'preact'
import Router, { RouterOnChangeArgs } from 'preact-router'
import { useState } from 'preact/hooks'
function wrapRoute(route: h.JSX.Element): h.JSX.Element {
return (
<section path={route.props.path} class="in page" key={route.props.path}>
{route}
</section>
)
}
type AnimatedRouterProps = {
children: h.JSX.Element[]
}
export const AnimatedRouter = ({ children }: AnimatedRouterProps) => {
const [previousEl, setPreviousEl] = useState<ComponentChildren | null>(null)
const [outerElement, setOuterElement] = useState<h.JSX.Element | null>(null)
const handleRouteChange = (e: RouterOnChangeArgs) => {
if (previousEl) {
setOuterElement(
<div class="out page" key={e.previous} onAnimationEnd={() => setOuterElement(null)}>
{previousEl}
</div>,
)
}
if (e.current) {
setPreviousEl(e.current.props.children)
}
}
return (
<Fragment>
<Router onChange={handleRouteChange}>{children.map(wrapRoute)}</Router>
{outerElement}
</Fragment>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment