Page Transition
A route transition container combining View Transitions concepts with overlay reveals, playing one of four transitions — fade, slide, cover, or wipe — whenever the route changes.
This is a WebberUI Pro component
The install command below needs a licence to run; without one it returns 401.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add "https://webberui.com/r/page-transition.en.json?t=<install token>"Playground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<PageTransition/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add "https://webberui.com/r/page-transition.en.json?t=<install token>"Or, once registries are configured in components.json, install it as @webberui/page-transition.
Usage
Wrap your page content in PageTransition and pass the value that changes with the route (usually the pathname) to transitionKey. In the Next.js App Router, the most natural place for this is template.tsx:
"use client";
import { usePathname } from "next/navigation";
import { PageTransition } from "@/components/ui/page-transition";
export default function Template({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
<PageTransition transitionKey={pathname} variant="cover" direction="right">
{children}
</PageTransition>
);
}Native View Transitions
If you want navigation to trigger the browser's native View Transitions (cross-page crossfades, shared-element morphs), wrap the update that changes the DOM with useViewTransition:
"use client";
import { useRouter } from "next/navigation";
import { useViewTransition } from "@/components/ui/page-transition";
export function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
const router = useRouter();
const startTransition = useViewTransition();
return (
<a
href={href}
onClick={(event) => {
event.preventDefault();
startTransition(() => router.push(href));
}}
>
{children}
</a>
);
}Browsers without View Transitions support simply run the update directly, degrading gracefully.
Props
PageTransition
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | Page content |
transitionKey | string | number | — | The transition trigger key; changing it plays the transition once (usually the pathname) |
variant | "fade" | "slide" | "cover" | "wipe" | "fade" | Transition style |
direction | "up" | "down" | "left" | "right" | "up" | Direction of the offset or the cover sweep |
duration | number | 0.6 | Total duration of the whole transition (seconds), split evenly between exit and enter |
distance | number | 24 | Offset distance for the slide variant (px) |
overlayClassName | string | — | Appended to the overlay className (cover / wipe), so you can override its background color |
className | string | — | Appended to the outer container className |
onTransitionComplete | () => void | — | Callback fired when the transition has completely finished |
useViewTransition()
Returns startTransition(update), where update is a function that changes the DOM (either synchronous or returning a Promise), and the return value is a Promise<void> that resolves when the transition ends.
How it works
- State-machine driven: internally it runs a three-stage state machine — exit → swap the content seamlessly at the peak of the cover → enter — advanced entirely by Motion's
onAnimationComplete, with no timers involved. - Overlay reveal:
coverslides a solid panel in to cover, then slides it out from the opposite side to reveal;wipesweeps across by scaling along the axis, switchingtransform-originautomatically between covering and revealing. The content swap happens at the exact moment the panel fully covers the view, so nothing visible jumps. - No animation on first load: the initial render matches the SSR output, and a transition only plays after
transitionKeychanges. - Rapid successive changes: changing
transitionKeyagain mid-transition jumps straight to the newest content once the current transition ends, rather than stacking up playbacks.
Accessibility
- When the user has "reduce motion" enabled at the system level, the content is swapped instantly with no offset or cover animation played at all.
- While a transition is running the outer container carries
aria-busy, and the overlay is hidden from assistive technology witharia-hiddenand ispointer-events-noneso it does not intercept interaction.
Preloader Collection
Three preloader overlay animations — text reveal, staircase slide, and pixel dissolve — each revealing the content with its own signature exit once loading finishes.
Confetti Feedback
A hand-built particle confetti celebration — bursting from an origin point, each piece with its own initial velocity, gravity, rotation, and drift, updated on rAF and reclaimed once it lands.