npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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-motion

Peer 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, star
  • circle-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-center
  • clip-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 theme
  • toggleTheme() – switch between light and dark
  • getTheme() / getResolvedTheme() – read current theme outside React
  • initTheme() – 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 sets class="light" or class="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

🔗 Links