Theme switching, cinematic
15 种形状揭开新主题,React / Vue / Next.js / Nuxt 通用。

Features
小而完整的动画层
约 95% 代码与框架无关,两个薄适配层覆盖 React 与 Vue 生态。
跨框架
一套核心,四种用法:React / Vue composable、Next.js 受控示例、Nuxt 模块自动导入。
React 18+Vue 3+Next.jsNuxt 3+
15 种动画
圆形 / 形状 / 百叶窗 / 扫描 / 格子 / 涟漪 / 扇形 / 双开门,方向与参数可调;9 个类型支持 reverse 反向揭开。
CIRCLERIPPLECLOCK_SWEEPBLINDS…
受控模式
不独占主题状态:next-themes 与 @nuxtjs/color-mode 用户直接接入,300ms 未同步自动直切。
next-themes@nuxtjs/color-mode
多实例同步
同页多个实例的 isDark 以 html class 为事实源镜像,其它标签页经 storage 事件同步。
observeThemeClassfinished
优雅降级
不支持 View Transitions、SSR、prefers-reduced-motion:跳过动画,状态永远正确。
SSR 安全reduced-motion
Playground
Try Different Animations
点击卡片中央按钮播放动画;BLINDS / SCAN / QR_GRID / CURTAIN 可在卡内切换方向,RIPPLE 可切换环带波长,FAN 可切换扇叶数, QR_GRID 可切换格距与方块 / 圆点形状。
duration
easing
CIRCLE
圆形扩散 · 圆心 = 点击位置
Duration750ms
Easingease-in-out
Reverse
CIRCLE_BLUR
圆形模糊扩散
Duration750ms
Easingease-in-out
Reverse
SQUARE
正方形扩散
Duration750ms
Easingease-in-out
Reverse
DIAMOND
菱形扩散
Duration750ms
Easingease-in-out
Reverse
RECTANGLE
矩形 · 贴合视口比例
Duration750ms
Easingease-in-out
Reverse
HEXAGON
六边形 · 尖顶朝上
Duration750ms
Easingease-in-out
TRIANGLE
三角形 · 顶点朝上
Duration750ms
Easingease-in-out
STAR
五角星 · 顶点朝上
Duration750ms
Easingease-in-out
BLINDS
百叶窗 · 叶宽与方向可调
Duration750ms
Easingease-in-out
Direction
Slat
SCAN
扫描 · 硬边扫开 + 前缘光束
Duration750ms
Easingease-in-out
Direction
QR_GRID
方块格子 · 格距与形状可调
Duration750ms
Easingease-in-out
Direction
Cell
RIPPLE
水滴涟漪 · 波源
Duration750ms
Easingease-in-out
Wave
Reverse
CLOCK_SWEEP
时钟扇形 · 轴心
Duration750ms
Easingease-in-out
Reverse
FAN
扇叶旋开 · 轴心
Duration750ms
Easingease-in-out
Blades
Reverse
CURTAIN
双开门 · 开合轴可调
Duration750ms
Easingease-in-out
Direction
Reverse
Quick Start
三行代码接入
四个入口,同一套 API。
npm install theme-switch-animation'use client'import { ThemeAnimationType, useThemeAnimation } from 'theme-switch-animation/react'export function ThemeToggle() {// 非受控:库管理 localStorage + <html> class// 多实例 / 跨标签页的 isDark 自动同步(以 html class 为事实源)const { ref, toggleTheme, isDark, finished } = useThemeAnimation({animationType: ThemeAnimationType.CIRCLE,duration: 750,})return (<button ref={ref} onClick={toggleTheme}>{isDark ? '🌙' : '☀️'}{/* finished:本次动画结束 Promise,可 await 做动画期间禁用 */}</button>)}