Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-next-theme

Package Overview
Dependencies
Maintainers
0
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-next-theme - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

scripts/themeScript.js

3

dist/index.js

@@ -1,2 +0,1 @@

import e,{useContext as t,useState as o,useEffect as r,createContext as m}from'react';const n=m(),c=()=>t(n),a='light',d='dark',i=({children:t})=>{const[m,c]=o(a);return r((()=>{if('undefined'!=typeof window){const e=(()=>{const e=window.localStorage.getItem('theme');return e||(window.matchMedia('(prefers-color-scheme: dark)').matches?d:a)})();c(e),document.documentElement.setAttribute('data-theme',e),localStorage.setItem('theme',e)}}),[]),e.createElement(n.Provider,{value:{theme:m,toggleTheme:()=>{const e=m===a?d:a;c(e),document.documentElement.setAttribute('data-theme',e),c(e)}}},t)};export{i as ThemeProvider,c as useTheme};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb250ZXh0L1RoZW1lQ29udGV4dC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgY3JlYXRlQ29udGV4dCwgdXNlQ29udGV4dCwgdXNlRWZmZWN0LCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcblxuY29uc3QgVGhlbWVDb250ZXh0ID0gY3JlYXRlQ29udGV4dCgpO1xuZXhwb3J0IGNvbnN0IHVzZVRoZW1lID0gKCkgPT4gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuXG5jb25zdCB0aGVtZXMgPSB7IGxpZ2h0OiAnbGlnaHQnLCBkYXJrOiAnZGFyaycgfVxuXG5jb25zdCBUaGVtZVByb3ZpZGVyID0gKHsgY2hpbGRyZW4gfSkgPT4ge1xuICBjb25zdCBbdGhlbWUsIHNldFRoZW1lXSA9IHVzZVN0YXRlKHRoZW1lcy5saWdodCk7XG5cblxuICBjb25zdCBnZXRJbml0aWFsVGhlbWUgPSAoKSA9PiB7XG4gICAgY29uc3Qgc3RvcmVkVGhlbWUgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RoZW1lJyk7XG4gICAgaWYgKHN0b3JlZFRoZW1lKSByZXR1cm4gc3RvcmVkVGhlbWU7XG5cbiAgICBjb25zdCB1c2VyUHJlZmVyZWRTY2hlbWUgPSB3aW5kb3cubWF0Y2hNZWRpYSgnKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKScpLm1hdGNoZXM7XG4gICAgcmV0dXJuIHVzZXJQcmVmZXJlZFNjaGVtZSA/IHRoZW1lcy5kYXJrIDogdGhlbWVzLmxpZ2h0O1xuICB9XG5cblxuICBjb25zdCB0b2dnbGVUaGVtZSA9ICgpID0+IHtcbiAgICBjb25zdCBuZXdUaGVtZSA9IHRoZW1lID09PSB0aGVtZXMubGlnaHQgPyB0aGVtZXMuZGFyayA6IHRoZW1lcz8ubGlnaHQ7XG4gICAgc2V0VGhlbWUobmV3VGhlbWUpO1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtdGhlbWUnLCBuZXdUaGVtZSk7XG4gICAgc2V0VGhlbWUobmV3VGhlbWUpO1xuICB9XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgY29uc3QgaW5pdGlhbFRoZW1lID0gZ2V0SW5pdGlhbFRoZW1lKCk7XG4gICAgICBzZXRUaGVtZShpbml0aWFsVGhlbWUpO1xuICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNldEF0dHJpYnV0ZSgnZGF0YS10aGVtZScsIGluaXRpYWxUaGVtZSk7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgndGhlbWUnLCBpbml0aWFsVGhlbWUpO1xuICAgIH1cbiAgfSwgW10pXG5cbiAgcmV0dXJuIChcbiAgICA8VGhlbWVDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt7IHRoZW1lLCB0b2dnbGVUaGVtZSB9fT5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L1RoZW1lQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgVGhlbWVQcm92aWRlcjsiXSwibmFtZXMiOlsiVGhlbWVDb250ZXh0IiwiY3JlYXRlQ29udGV4dCIsInVzZVRoZW1lIiwidXNlQ29udGV4dCIsInRoZW1lcyIsIlRoZW1lUHJvdmlkZXIiLCJjaGlsZHJlbiIsInRoZW1lIiwic2V0VGhlbWUiLCJ1c2VTdGF0ZSIsInVzZUVmZmVjdCIsIndpbmRvdyIsImluaXRpYWxUaGVtZSIsImdldEluaXRpYWxUaGVtZSIsInN0b3JlZFRoZW1lIiwibG9jYWxTdG9yYWdlIiwiZ2V0SXRlbSIsIm1hdGNoTWVkaWEiLCJtYXRjaGVzIiwiZG9jdW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiLCJzZXRBdHRyaWJ1dGUiLCJzZXRJdGVtIiwiUmVhY3QiLCJjcmVhdGVFbGVtZW50IiwiUHJvdmlkZXIiLCJ2YWx1ZSIsInRvZ2dsZVRoZW1lIiwibmV3VGhlbWUiXSwibWFwcGluZ3MiOiJzRkFFQSxNQUFNQSxFQUFlQyxJQUNSQyxFQUFXQSxJQUFNQyxFQUFXSCxHQUVuQ0ksRUFBa0IsUUFBbEJBLEVBQWlDLE9BRWpDQyxFQUFnQkEsRUFBR0MsZUFDdkIsTUFBT0MsRUFBT0MsR0FBWUMsRUFBU0wsR0E0Qm5DLE9BVEFNLEdBQVUsS0FDUixHQUFzQixvQkFBWEMsT0FBd0IsQ0FDakMsTUFBTUMsRUFsQmNDLE1BQ3RCLE1BQU1DLEVBQWNILE9BQU9JLGFBQWFDLFFBQVEsU0FDaEQsT0FBSUYsSUFFdUJILE9BQU9NLFdBQVcsZ0NBQWdDQyxRQUNqRGQsRUFBY0EsRUFBWSxFQWEvQlMsR0FDckJMLEVBQVNJLEdBQ1RPLFNBQVNDLGdCQUFnQkMsYUFBYSxhQUFjVCxHQUNwREcsYUFBYU8sUUFBUSxRQUFTVixFQUNoQyxJQUNDLElBR0RXLEVBQUFDLGNBQUN4QixFQUFheUIsU0FBUSxDQUFDQyxNQUFPLENBQUVuQixRQUFPb0IsWUFqQnJCQSxLQUNsQixNQUFNQyxFQUFXckIsSUFBVUgsRUFBZUEsRUFBY0EsRUFDeERJLEVBQVNvQixHQUNUVCxTQUFTQyxnQkFBZ0JDLGFBQWEsYUFBY08sR0FDcERwQixFQUFTb0IsRUFBUyxJQWNmdEIsRUFDcUIifQ==
import e,{useContext as t,useState as o,useEffect as m,createContext as r}from'react';const a=r(),c=()=>t(a),n='light',d='dark',l=({children:t})=>{const[r,c]=o((()=>'undefined'!=typeof window?localStorage.getItem('theme')||(window.matchMedia('(prefers-color-scheme: dark)').matches?d:n):n));return m((()=>{document.documentElement.setAttribute('data-theme',r)}),[r]),e.createElement(a.Provider,{value:{theme:r,toggleTheme:()=>{const e=r===n?d:n;c(e),document.documentElement.setAttribute('data-theme',e),localStorage.setItem('theme',e)}}},t)};export{l as ThemeProvider,c as useTheme};
{
"name": "react-next-theme",
"version": "1.0.2",
"version": "1.0.3",
"type": "module",

@@ -9,4 +9,10 @@ "description": "A simple and flexible theme switcher for React and Next.js, supporting light and dark modes with localStorage and system preferences.",

"build:dev": "rollup -c --environment NODE_ENV:development",
"build": "rollup -c --environment NODE_ENV:production"
"build": "rollup -c --environment NODE_ENV:production",
"postinstall": "node postinstall.js"
},
"files": [
"dist",
"scripts/themeScript.js",
"src"
],
"keywords": [

@@ -13,0 +19,0 @@ "react-next-theme",

# react-next-theme
`react-next-theme` is a simple and flexible theme switcher for React and Next.js. It allows for seamless toggling between light and dark modes, supports user preferences, and stores the selected theme in local storage.
**`react-next-theme`** is a simple and flexible theme switcher for React and Next.js applications, supporting both light and dark modes with seamless theme toggling. It also provides a solution for preventing flickering during page loads by automatically applying the user’s theme preference from `localStorage` or system settings.
## Features
- **Automatic Theme Detection**: Detects system-level theme preferences (light/dark).
- **Persistent Theme**: Automatically saves and loads the user's preferred theme using `localStorage`.
- **Easy Integration**: Simple integration with React and Next.js projects.
- **CSS Variables**: Uses CSS variables for dynamic theming.
- Seamless light/dark mode switching.
- Works with **React** and **Next.js** (both App Router and Page Router).
- Automatically applies the preferred theme on page load.
- Uses a lightweight theme script for fast initial theme application to avoid flickering.
- Theme preferences are persisted in `localStorage`.
## Installation
You can install the `react-next-theme` package using npm or yarn:
You can install `react-next-theme` via **npm** or **yarn**:
### Using npm:
```bash

@@ -20,3 +23,3 @@ npm install react-next-theme

or
### Using yarn:

@@ -27,252 +30,189 @@ ```bash

After installation, a script (`react-next-theme-script.js`) will be automatically copied to your **public** folder. This script applies the initial theme before React renders to avoid flickering.
## Usage
### React
### 1. Next.js (App Router or Page Router)
To use the package in a React application, follow these steps:
#### **App Router (`app/layout.js`)**
1. **Wrap Your App with `ThemeProvider`**
To use `react-next-theme` in the **Next.js App Router**, follow these steps:
In your main file (e.g., `src/main.jsx` or `src/index.js`), wrap your app in the `ThemeProvider` to provide theme context to the entire application.
1. Import the theme script using the Next.js `<Script>` component in your **`app/layout.js`**:
```jsx
// src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css'; // Import your global CSS
import { ThemeProvider } from 'react-next-theme';
```js
import Script from 'next/script';
import { ThemeProvider } from 'react-next-theme';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<ThemeProvider>
<App />
</ThemeProvider>
</React.StrictMode>
);
```
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
{/* Load the theme script before React hydrates the page */}
<Script src="/react-next-theme-script.js" strategy="beforeInteractive" />
</head>
<body>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
}
```
2. **Use `useTheme` to Toggle Theme**
2. Use the `ThemeProvider` to wrap your application components to enable theme toggling.
In your components, you can use the `useTheme` hook to toggle between light and dark modes:
#### **Page Router (`pages/_document.js`)**
```jsx
// src/App.jsx
import React from 'react';
import { useTheme } from 'react-next-theme';
To use it in **Next.js Page Router**, include the theme script in **`pages/_document.js`**:
const App = () => {
const { theme, toggleTheme } = useTheme();
```js
import { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';
return (
<div>
<h1>Current Theme: {theme}</h1>
<button onClick={toggleTheme}>
Toggle to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
</div>
);
};
export default function Document() {
return (
<Html>
<Head>
{/* Load the theme script */}
<Script src="/react-next-theme-script.js" strategy="beforeInteractive" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
```
export default App;
```
You can then use the `ThemeProvider` in **`pages/_app.js`** to wrap your application:
3. **Add CSS for Themes**
```js
import { ThemeProvider } from 'react-next-theme';
import '../styles/globals.css';
Add CSS for your light and dark themes in your global styles (`src/index.css`):
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
```css
/* src/index.css */
/* Default Light Theme */
:root {
--bg-color: #ffffff;
--text-color: #213547;
--link-color: #646cff;
--link-hover-color: #747bff;
--button-bg-color: #f9f9f9;
--button-text-color: #213547;
}
export default MyApp;
```
body {
background-color: var(--bg-color);
color: var(--text-color);
}
### 2. React (Create React App)
[data-theme='dark'] {
--bg-color: #242424;
--text-color: rgba(255, 255, 255, 0.87);
--link-color: #646cff;
--link-hover-color: #535bf2;
--button-bg-color: #1a1a1a;
--button-text-color: #ffffff;
}
```
In **React projects**, you need to include the theme script in your **`public/index.html`** file:
### Next.js
```html
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React App</title>
<!-- Load the theme script to apply the theme before the app renders -->
<script src="%PUBLIC_URL%/react-next-theme-script.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
```
`react-next-theme` works seamlessly with both the **App Router** and **Pages Router** in Next.js.
Then, wrap your app with the `ThemeProvider` in **`src/index.js`**:
#### Next.js (App Router)
```js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { ThemeProvider } from 'react-next-theme';
1. **Wrap Your App with `ThemeProvider`**
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById('root')
);
```
In `app/layout.js` or `app/layout.tsx`, wrap your app with `ThemeProvider`:
### 3. Toggling Theme in Your Application
```jsx
// app/layout.js
import './globals.css'; // Import global CSS
import { ThemeProvider } from 'react-next-theme';
The `useTheme` hook allows you to toggle between light and dark modes. Here’s an example of how to use it:
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}
```
```js
import React from 'react';
import { useTheme } from 'react-next-theme';
2. **Use `useTheme` to Toggle Theme**
function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
In any page or component, use the `useTheme` hook:
return (
<button onClick={toggleTheme}>
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'}
</button>
);
}
```jsx
// app/page.js
import { useTheme } from 'react-next-theme';
export default ThemeToggle;
```
export default function HomePage() {
const { theme, toggleTheme } = useTheme();
### 4. Customizing the Theme
return (
<div>
<h1>Current Theme: {theme}</h1>
<button onClick={toggleTheme}>
Toggle to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
</div>
);
}
```
The theme is applied using a `data-theme` attribute on the `<html>` element. You can define your own custom CSS styles for light and dark modes in your stylesheets:
3. **Add Global CSS**
```css
/* Default light theme */
:root {
--background-color: white;
--text-color: black;
}
Add your CSS for light and dark themes in `globals.css`:
html[data-theme='dark'] {
--background-color: black;
--text-color: white;
}
```css
/* styles/globals.css */
:root {
--bg-color: #ffffff;
--text-color: #213547;
--link-color: #646cff;
--link-hover-color: #747bff;
--button-bg-color: #f9f9f9;
--button-text-color: #213547;
}
body {
background-color: var(--background-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
```
body {
background-color: var(--bg-color);
color: var(--text-color);
}
### 5. How the Theme Script Works
[data-theme='dark'] {
--bg-color: #242424;
--text-color: rgba(255, 255, 255, 0.87);
--link-color: #646cff;
--link-hover-color: #535bf2;
--button-bg-color: #1a1a1a;
--button-text-color: #ffffff;
}
```
The `react-next-theme-script.js` file is a small JavaScript file that runs before the app loads, ensuring that the theme is set early. It checks the `localStorage` for the user's theme preference or falls back to the system's preferred color scheme:
#### Next.js (Pages Router)
```js
(function () {
const storedTheme = localStorage.getItem('theme');
if (storedTheme) {
document.documentElement.setAttribute('data-theme', storedTheme);
} else {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
}
})();
```
1. **Wrap Your App with `ThemeProvider`**
### 6. Example Usage
In `pages/_app.js`, wrap your app with `ThemeProvider`:
Here’s an example of how you can use `react-next-theme` in your Next.js or React app to create a smooth theme-switching experience without flickering:
```jsx
// pages/_app.js
import '../styles/globals.css';
import { ThemeProvider } from 'react-next-theme';
1. Add the script to your project (Next.js or React).
2. Use the `ThemeProvider` to manage theme state.
3. Use the `useTheme` hook to toggle the theme.
export default function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
```
2. **Use `useTheme` to Toggle Theme**
In any page or component, use the `useTheme` hook:
```jsx
// pages/index.js
import { useTheme } from 'react-next-theme';
export default function Home() {
const { theme, toggleTheme } = useTheme();
return (
<div>
<h1>Current Theme: {theme}</h1>
<button onClick={toggleTheme}>
Toggle to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
</div>
);
}
```
3. **Add Global CSS**
Add your CSS in `globals.css`:
```css
/* styles/globals.css */
:root {
--bg-color: #ffffff;
--text-color: #213547;
--link-color: #646cff;
--link-hover-color: #747bff;
--button-bg-color: #f9f9f9;
--button-text-color: #213547;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
}
[data-theme='dark'] {
--bg-color: #242424;
--text-color: rgba(255, 255, 255, 0.87);
--link-color: #646cff;
--link-hover-color: #535bf2;
--button-bg-color: #1a1a1a;
--button-text-color: #ffffff;
}
```
## Local Storage Support
The `react-next-theme` package automatically stores the user's theme preference in `localStorage` and loads it on page reload. This ensures a consistent experience across sessions.
## System Preferences Detection
`react-next-theme` also detects the user's system-level theme preference (light or dark) using the `prefers-color-scheme` media query and applies it as the default theme if no preference is stored in `localStorage`.
---
## License
`react-next-theme` is licensed under the [MIT License](LICENSE).
```
This project is licensed under the **MIT License**.
---
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc