css-theme-transition
v2.0.6
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 dependency).
✨ Features
- No provider – Works in any React or Next.js app without wrapping your app (no dependency required)
- 16 preset demos – Circle, circle-blur, 6× circle-pivot positions, star, star-blur, diamond, diamond-blur, triangle, triangle-blur, hexagon, hexagon-blur
- No border – View transition overlays and the toggle wrapper use no border/outline for a clean look
- 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 – All 16 variant CSS files are included; no separate CSS import needed
- No framer-motion – Icons use Tailwind CSS utilities (
animate-in,fade-in); only React peer deps - React & Next.js – Same API for both; client-only, no server components
📦 Install
npm install css-theme-transition
# or
pnpm add css-theme-transition
# or
yarn add css-theme-transitionPeer dependencies: react >= 18, react-dom >= 18. No next-themes required.
🚀 Usage
Next.js (App Router)
Use in any client component (no root layout or provider setup). CSS is auto-injected, but you can also import the CSS file if you prefer.
"use client";
import ThemeTransition from "css-theme-transition";
// Optional: manual CSS import
import "css-theme-transition/theme-transition.css";
export default function Header() {
return (
<header>
<ThemeTransition variant="star" />
</header>
);
}React (Vite, Create React App, Vite, etc.)
Same API. In a typical React SPA entry:
import React from "react";
import ReactDOM from "react-dom/client";
import ThemeTransition from "css-theme-transition";
// Optional: manual CSS import
import "css-theme-transition/theme-transition.css";
import "./index.css";
function App() {
return (
<div className="flex justify-center items-center h-screen">
<ThemeTransition variant="star" />
</div>
);
}
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);One-line summary
import ThemeTransition from "css-theme-transition";
<ThemeTransition variant="star" />;No ThemeProvider, no layout changes. No CSS import needed — animation styles for all built-in variants 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 | Not needed; script is injected by the component | Same |
| 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 |
Flash prevention
<ThemeTransition /> automatically injects a tiny inline script (themeInitScript) before React mounts to set the correct initial light / dark class on <html> using the saved or system theme. You don’t need any layout changes or manual <Script> tags in Next.js.
🎨 Variants and positions
Circle family
circle(default)circle-blurcircle-pivot– positions:top-left,top-right,bottom-left,bottom-right,top-center,bottom-center
Star
starstar-blur
Diamond
diamonddiamond-blur
Triangle
triangletriangle-blur
Hexagon
hexagonhexagon-blur
Examples
<ThemeTransition />
<ThemeTransition variant="star" />
<ThemeTransition variant="circle-blur" />
<ThemeTransition variant="circle-pivot" position="top-right" />🔌 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). The default icons inside <ThemeTransition /> use Tailwind CSS utility classes (animate-in, fade-in, duration-200) for simple entrance animations — no framer-motion required.
📋 CSS and styles
Default: You do not need to import any CSS. The component bundle includes a shared base (no border/outline on view transitions) plus all 16 variant styles (basic shapes, blur variants, pivot). They are injected when the component is used. View transition overlays and the toggle wrapper are borderless. The library sets
class="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
