css-theme-transition
v2.0.1
Published
View Transition theme switch animations for React and Next.js — no provider required
Readme
css-theme-transition
View Transition API–based theme switch animations for React and Next.js. No provider or layout setup — drop in the component and go. v2.0 uses a built-in theme engine (no next-themes dependency).
✨ Features
- No provider – Works in any React or Next.js app without wrapping your app
- 18+ animation variants – Circle, square, diamond, star, blur effects, pivot positions, and more
- Built-in theme engine – Light / dark / system, persisted in
localStorage - Flash prevention – Inline script runs before paint to avoid theme flash on load
- Styles bundled – Animation CSS (circle, star, etc.) is included with the component; no separate CSS import needed
- React & Next.js – Same API for both; client-only, no server components
📦 Install
npm install css-theme-transition framer-motion
# or
pnpm add css-theme-transition framer-motion
# or
yarn add css-theme-transition framer-motionPeer dependencies: react >= 18, react-dom >= 18, framer-motion >= 10
🚀 Usage
Next.js (App Router)
Use in any client component (no root layout or provider setup):
"use client";
import { ThemeTransition } from "css-theme-transition";
export default function Header() {
return (
<header>
<ThemeTransition variant="circle-pivot" position="top-right" />
</header>
);
}React (Vite, Create React App, etc.)
Same usage. Ensure your app has a root that supports client-side rendering (e.g. default Vite/CRA setup):
import { ThemeTransition } from "css-theme-transition";
function App() {
return (
<div>
<ThemeTransition variant="circle" />
</div>
);
}One-line summary
import { ThemeTransition } from "css-theme-transition";
<ThemeTransition variant="circle-pivot" position="top-right" />No ThemeProvider, no layout changes. No CSS import needed — animation styles (circle, star, blur, pivot, etc.) are bundled with the component and applied automatically. The library adds the light or dark class to <html> and injects the transition CSS.
📖 Next.js vs React – differences
| Topic | Next.js | React (Vite / CRA) |
|--------|---------|---------------------|
| Provider | Not needed | Not needed |
| Layout | Optional: add init script for zero flash (see below) | Same; script is injected by the component |
| Where to use | Any "use client" component | Any component |
| CSS | Auto-injected by component, or import once in layout | Auto-injected, or import in index.tsx / App.tsx |
Optional: zero flash in Next.js
To avoid a brief theme flash before the component mounts, you can run the theme init script before React hydrates. In your root layout:
// app/layout.tsx
import Script from "next/script";
const themeScript = `
(function () {
try {
var saved = localStorage.getItem("theme-transition");
var system = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
var theme = saved || "system";
var resolved = theme === "system" ? system : theme;
document.documentElement.classList.add(resolved);
} catch (e) {}
})();
`;
export default function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<Script id="theme-init" strategy="beforeInteractive">
{themeScript}
</Script>
</head>
<body>{children}</body>
</html>
);
}If you don’t add this, the component still injects the script when it mounts, which is usually good enough.
🎨 Variants and positions
Basic shapes
circle(default),square,diamond,triangle,hexagon,starcircle-ring,frame
Blur effects
circle-blur,square-blur,rectangle-blur,diamond-blur,triangle-blur,hexagon-blur,star-blur
Pivot (with position)
circle-pivot– positions:top-left,top-right,bottom-left,bottom-right,top-center,bottom-centerclip-path-pivot,clip-path-pivot-2– positions:top-left,top-right,bottom-left,bottom-right,center,diagonal-left,diagonal-right
Examples
<ThemeTransition />
<ThemeTransition variant="star" />
<ThemeTransition variant="circle-blur" />
<ThemeTransition variant="circle-pivot" position="top-right" />
<ThemeTransition variant="clip-path-pivot" position="center" />
<ThemeTransition variant="circle">
<CustomIcon />
</ThemeTransition>🔌 Advanced API (React & Next.js)
For custom UI or logic, you can use the theme store and hook.
import {
ThemeTransition,
useThemeTransition,
setTheme,
getTheme,
getResolvedTheme,
initTheme,
} from "css-theme-transition";
import type { Theme } from "css-theme-transition";
// In a client component
function MyControls() {
const { theme, resolvedTheme, setTheme, toggleTheme } = useThemeTransition();
return (
<div>
<ThemeTransition variant="circle" />
<p>Current: {theme} (resolved: {resolvedTheme})</p>
<button onClick={() => setTheme("light")}>Light</button>
<button onClick={() => setTheme("dark")}>Dark</button>
<button onClick={() => setTheme("system")}>System</button>
<button onClick={toggleTheme}>Toggle</button>
</div>
);
}theme–"light" | "dark" | "system"resolvedTheme–"light" | "dark"(what’s actually applied)setTheme(theme)– set and persist themetoggleTheme()– switch between light and darkgetTheme()/getResolvedTheme()– read current theme outside ReactinitTheme()– run once on mount (called by the component; only needed if you don’t use<ThemeTransition />)
Theme is stored in localStorage under the key theme-transition and applied as a class on document.documentElement (light or dark).
📋 CSS and styles
Default: You do not need to import any CSS. The component bundle includes all animation styles (from
index.css: circle, square, star, diamond, triangle, hexagon, blur variants, pivot, clip-path). They are injected when the component is used. The library also setsclass="light"orclass="dark"on<html>so transitions work correctly.Optional manual import: If you prefer to load the stylesheet yourself (e.g. in your root layout or entry):
import "css-theme-transition/theme-transition.css";Or in global CSS:
@import "css-theme-transition/theme-transition.css";
🌐 Browser support
Uses the View Transition API. Supported in Chrome 111+, Edge 111+, Opera 97+. Safari has experimental support; Firefox not yet. In unsupported browsers, theme still toggles without animation.
📄 License
ISC
