WebberUI

Page Transition

路由過場容器,結合 View Transitions 觀念與覆蓋揭示,於路由改變時播放淡入、滑動、覆蓋或抹除四款過場。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

0.6
24
<PageTransition />

安裝

npx shadcn@latest add https://webberui.com/r/page-transition.json

或在 components.json 設定 registries 後,改用 @webberui/page-transition 安裝。

安裝依賴後,從 registry JSON(/r/page-transition.jsonfiles[0].content)複製 page-transition.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

使用

把頁面內容包進 PageTransition,並將會隨路由改變的值(通常是 pathname)傳給 transitionKey。在 Next.js App Router 中,最自然的位置是 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>
  );
}

原生 View Transitions

若想在導覽時觸發瀏覽器原生的 View Transitions(跨頁交叉淡入、共享元素 morph),可用 useViewTransition 包住會改變 DOM 的更新:

"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>
  );
}

不支援 View Transitions 的瀏覽器會直接執行更新,行為優雅降級。

Props

PageTransition

Prop型別預設值說明
childrenReact.ReactNode頁面內容
transitionKeystring | number過場觸發鍵,改變即播放一次過場(通常傳 pathname)
variant"fade" | "slide" | "cover" | "wipe""fade"過場款式
direction"up" | "down" | "left" | "right""up"位移/覆蓋掃動的方向
durationnumber0.6整段過場的總時長(秒),出場與進場各半
distancenumber24slide 款式的位移距離(px)
overlayClassNamestring覆蓋層(coverwipe)的追加 className,可覆寫底色
classNamestring追加到外層容器的 className
onTransitionComplete() => void過場完整結束時的回呼

useViewTransition()

回傳 startTransition(update)update 為會改變 DOM 的函式(可為同步或回傳 Promise),回傳解析於過場結束的 Promise<void>

細節

  • 狀態機驅動:內部以「出場 → 於覆蓋高峰無縫替換內容 → 進場」三段狀態機運作,全程僅靠 Motion 的 onAnimationComplete 推進,不使用任何計時器。
  • 覆蓋揭示cover 以實心面板滑入覆蓋、由反側滑出揭示;wipe 以沿軸線縮放的方式抹過,覆蓋與揭示自動切換 transform-origin。內容替換發生在面板完全覆蓋的瞬間,肉眼看不到跳動。
  • 首次載入不動畫:初次渲染與 SSR 輸出一致,只有在 transitionKey 改變後才播放過場。
  • 快速連續切換:過場進行中再次改變 transitionKey,會在當前過場結束後直接跳到最新內容,不會堆疊播放。

可及性

  • 使用者系統開啟「減少動態效果」時,內容直接即時替換,不播放任何位移或覆蓋動畫。
  • 過場進行中外層容器帶 aria-busy,覆蓋層以 aria-hidden 對輔助科技隱藏、且 pointer-events-none 不攔截操作。

On this page