Theme Toggle
明暗主題切換按鈕:View Transitions 從點擊位置圓形擴散,Sun/Moon 圖示旋轉過渡。
載入預覽⋯
npx shadcn@latest add https://webberui.com/r/theme-toggle.jsonPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
220
<ThemeToggle />
安裝
npx shadcn@latest add https://webberui.com/r/theme-toggle.json安裝時會一併寫入 --wb-duration-fast、--wb-ease-out CSS 變數到你的全域樣式。
使用
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 | 220 | 圓形擴散動畫時長(毫秒)。過場期間整頁是點陣快照,文字會發虛,所以刻意偏短 |
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 - 使用者系統開啟「減少動態效果」時,退化為直接切換,圖示過渡改為淡入淡出