Theme Toggle
明暗主題切換按鈕:View Transitions 從點擊位置圓形擴散,Sun/Moon 圖示旋轉過渡。
載入預覽⋯
安裝
npx shadcn@latest add https://webberui.com/r/theme-toggle.json安裝時會一併寫入 --wb-duration-fast、--wb-ease-out CSS 變數到你的全域樣式。
安裝依賴後,複製 theme-toggle.tsx 到你的 components/ui/ 目錄,並在全域 CSS 加入:
npm install motion lucide-react clsx tailwind-merge:root {
--wb-duration-fast: 200ms;
--wb-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}View Transitions 需要的全域樣式(關閉預設 cross-fade)已由元件內部的 <style> 注入,不需要另外設定。
使用
import { ThemeToggle } from "@/components/ui/theme-toggle";
// 未受控:自動 toggle html 的 dark class 並寫入 localStorage("theme")
<ThemeToggle />
// 受控:搭配 next-themes 等主題方案
<ThemeToggle
isDark={resolvedTheme === "dark"}
onToggle={(next) => setTheme(next ? "dark" : "light")}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
isDark | boolean | — | 受控模式:目前是否為深色主題。不傳則元件自行管理 html.dark 與 localStorage |
onToggle | (next: boolean) => void | — | 切換時觸發,回傳切換後是否為深色。受控模式下請在此更新主題狀態 |
duration | number | 500 | 圓形擴散動畫時長(毫秒) |
className | string | — | 額外樣式 |
細節
- View Transitions 支援度:Chrome / Edge 111+、Safari 18+ 支援
document.startViewTransition;Firefox 尚未支援。不支援的瀏覽器會直接切換主題(無擴散動畫),功能完全不受影響 - 圓形擴散:以點擊座標為圓心,半徑取到視口最遠角落的距離,對
::view-transition-new(root)執行clipPath動畫;鍵盤觸發時以按鈕中心為圓心 - 受控模式:
onToggle內的狀態更新會在startViewTransitioncallback 中以flushSync同步套用,確保快照時機正確 - SSR 安全:未受控時掛載後才讀取
html.dark,掛載前渲染中性圖示避免 hydration mismatch - 使用者系統開啟「減少動態效果」時,退化為直接切換,圖示過渡改為淡入淡出