Skip to content

Instantly share code, notes, and snippets.

@mike-at-redspace
Created September 19, 2023 03:02
Show Gist options
  • Save mike-at-redspace/09e573463398fdc97f910b2286d4c10f to your computer and use it in GitHub Desktop.
Save mike-at-redspace/09e573463398fdc97f910b2286d4c10f to your computer and use it in GitHub Desktop.
usePageTransition
function usePageTransition({
beforeChange,
afterChange,
done,
}) {
const startResolverRef = useRef(null);
const dataRef = useRef(null);
const transitionRef = useRef(null);
useLayoutEffect(() => {
if (startResolverRef.current === null) return;
afterChangeRef.current?.(dataRef.current, transitionRef.current);
startResolverRef.current();
startResolverRef.current = null;
});
return async ({
classNames = [],
data,
} = {}) => {
if (!('startViewTransition' in document) || reducedMotionMedia?.matches) {
return;
}
return new Promise((resolve) => {
dataRef.current = data;
document.documentElement.classList.add(...classNames);
const transition = document.startViewTransition(async () => {
resolve();
// Wait for the next update
await new Promise((resolve) => (startResolverRef.current = resolve));
});
transitionRef.current = transition;
beforeChange?.(data, transition);
globalThis.ongoingTransition = transition;
transition.finished
.finally(() => {
globalThis.ongoingTransition = undefined;
document.documentElement.classList.remove(...classNames);
done?.(data);
})
.catch(() => {});
});
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment