react-next-theme
Advanced tools
Comparing version 1.1.0 to 1.1.1
{ | ||
"name": "react-next-theme", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"type": "module", | ||
@@ -22,5 +22,13 @@ "description": "A simple and flexible theme switcher for React and Next.js, supporting light and dark modes with localStorage and system preferences.", | ||
"light-mode", | ||
"dark theme", | ||
"light theme", | ||
"theme-toggle", | ||
"react-theme", | ||
"next-theme" | ||
"next-theme", | ||
"theme provider", | ||
"React dark mode", | ||
"Next.js dark mode", | ||
"custom themes", | ||
"user preference theme", | ||
"dark mode toggle" | ||
], | ||
@@ -27,0 +35,0 @@ "author": "Mesu", |
449
README.md
@@ -1,258 +0,302 @@ | ||
Sure! Here's the complete **`README.md`** file, including instructions for both **npm** and **yarn**, detailed usage for **React**, **Next.js (Pages Router and App Router)**, and the **CSS** you provided. | ||
# react-next-theme | ||
`react-next-theme` is a lightweight, customizable theme switcher for React and Next.js applications, supporting light and dark modes. It detects system preferences, applies the theme instantly, and prevents a white flash on page load. | ||
## Key Features | ||
- **Light and Dark Mode Support**: Allows seamless theme switching. | ||
- **System Preference Detection**: Automatically detects and applies the user’s system theme preference. | ||
- **No White Flash on Load**: Instantly applies the theme for a smooth user experience. | ||
- **Easy Setup**: Works seamlessly in React and Next.js (supports both Page and App Routers). | ||
--- | ||
# react-next-theme | ||
## Common Setup Instructions | ||
`react-next-theme` is a simple and flexible theme switcher for React and Next.js applications, supporting light and dark modes. It provides a seamless solution for managing themes across your applications with automatic theme detection based on system preferences and local storage. | ||
1. **Install the Package** | ||
## Features | ||
```bash | ||
npm install react-next-theme | ||
``` | ||
- Supports **light** and **dark** modes. | ||
- Automatically respects system preferences for dark mode. | ||
- Easy to integrate in **React** and **Next.js** applications (both **App Router** and **Pages Router**). | ||
- Prevents the white flash on page load by applying the correct theme immediately. | ||
- Customizable and extendable for your project needs. | ||
or | ||
## Installation | ||
```bash | ||
yarn add react-next-theme | ||
``` | ||
You can install the package via **npm** or **yarn**. | ||
2. **Create CSS for Theme Variables** | ||
### Using npm | ||
Define theme colors in a CSS file. You can either create a `theme.css` file in the `public` folder or add these styles directly to `index.css` (React) or `globals.css` (Next.js). | ||
```bash | ||
npm install react-next-theme | ||
``` | ||
```css | ||
/* Light and dark mode theme variables */ | ||
:root { | ||
--background-color: white; | ||
--text-color: black; | ||
} | ||
### Using yarn | ||
html[data-theme='dark'] { | ||
--background-color: black; | ||
--text-color: white; | ||
} | ||
```bash | ||
yarn add react-next-theme | ||
``` | ||
body { | ||
background-color: var(--background-color); | ||
color: var(--text-color); | ||
transition: background-color 0.3s, color 0.3s; | ||
} | ||
``` | ||
--- | ||
## Basic Setup | ||
## React Setup (Create React App or Vite) | ||
### 1. Add Theme-Specific CSS Variables | ||
1. **Add Theme Script to `public/index.html`** | ||
To ensure the theme is correctly applied to your application, include the following CSS in your global styles (`index.css` or `globals.css` depending on your setup): | ||
you can change color as you want. | ||
To ensure the theme is applied before the app mounts, create a `theme-script.js` file in the `public` folder with the following code: | ||
```css | ||
:root { | ||
--background-color: white; | ||
--text-color: black; | ||
} | ||
```js | ||
// public/theme-script.js | ||
(function() { | ||
const storedTheme = localStorage.getItem('theme'); | ||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||
const theme = storedTheme || (prefersDark ? 'dark' : 'light'); | ||
document.documentElement.setAttribute('data-theme', theme); | ||
})(); | ||
``` | ||
html[data-theme='dark'] { | ||
--background-color: black; | ||
--text-color: white; | ||
} | ||
Then, link the script in `public/index.html`: | ||
body { | ||
background-color: var(--background-color); | ||
color: var(--text-color); | ||
transition: background-color 0.3s, color 0.3s; | ||
} | ||
``` | ||
```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> | ||
This CSS sets the background and text colors based on the `data-theme` attribute applied to the `<html>` element. | ||
<!-- Link to theme initialization script --> | ||
<script src="%PUBLIC_URL%/theme-script.js"></script> | ||
--- | ||
<!-- Link to CSS file --> | ||
<link rel="stylesheet" href="%PUBLIC_URL%/theme.css" /> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
</body> | ||
</html> | ||
``` | ||
## Usage in **React** (Create React App or Vite) | ||
2. **Wrap Your App with `ThemeProvider` in `src/index.js`** | ||
### 1. Inject Theme Initialization Script and Style | ||
Wrap your main app component with `ThemeProvider` to enable dynamic theme switching. | ||
To prevent a white flash on page load, you need to inject a script that applies the correct theme before React mounts. Modify your **`public/index.html`** or **`index.html`** file: | ||
```js | ||
// src/index.js or src/main.js | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import App from './App'; | ||
import { ThemeProvider } from 'react-next-theme'; | ||
```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> | ||
ReactDOM.render( | ||
<ThemeProvider> | ||
<App /> | ||
</ThemeProvider>, | ||
document.getElementById('root') | ||
); | ||
``` | ||
<!-- Insert the theme initialization style of the avobe style --> | ||
<!-- <link rel="stylesheet" href="insert css file link"> --> | ||
3. **Use the `useTheme` Hook in Components** | ||
<!-- Insert the theme initialization script --> | ||
<script> | ||
(function() { | ||
const storedTheme = localStorage.getItem('theme'); | ||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||
const theme = storedTheme || (prefersDark ? 'dark' : 'light'); | ||
document.documentElement.setAttribute('data-theme', theme); | ||
})(); | ||
</script> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
</body> | ||
</html> | ||
``` | ||
Use the `useTheme` hook to toggle themes in any component. Here’s an example for a button in `App.js`: | ||
### 2. Use `ThemeProvider` in `src/index.js` or `src/main.js` | ||
```js | ||
// src/App.js | ||
import React from 'react'; | ||
import { useTheme } from 'react-next-theme'; | ||
Wrap your app with the `ThemeProvider` to handle dynamic theme switching: | ||
function App() { | ||
const { theme, toggleTheme } = useTheme(); | ||
```js | ||
// src/index.js or src/main.js | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import App from './App'; | ||
import { ThemeProvider } from 'react-next-theme'; | ||
return ( | ||
<div> | ||
<h1>{theme === 'light' ? 'Light Mode' : 'Dark Mode'}</h1> | ||
<button onClick={toggleTheme}> | ||
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'} | ||
</button> | ||
</div> | ||
); | ||
} | ||
ReactDOM.render( | ||
<ThemeProvider> | ||
<App /> | ||
</ThemeProvider>, | ||
document.getElementById('root') | ||
); | ||
``` | ||
export default App; | ||
``` | ||
### 3. Use the `useTheme` Hook in Your Components | ||
--- | ||
you can change the button or modify as your need | ||
## Next.js (Page Router) Setup | ||
```js | ||
// src/App.js | ||
import React from 'react'; | ||
import { useTheme } from 'react-next-theme'; | ||
1. **Theme Initialization Script in `_document.js`** | ||
function App() { | ||
const { theme, toggleTheme } = useTheme(); | ||
To apply the theme before Next.js renders the app, you can either use `getThemeScript` from `react-next-theme` or link a separate script file. | ||
return ( | ||
<div> | ||
<h1>{theme === 'light' ? 'Light Mode' : 'Dark Mode'}</h1> | ||
<button onClick={toggleTheme}> | ||
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'} | ||
</button> | ||
</div> | ||
); | ||
} | ||
- **Option A: Use `getThemeScript` directly**: | ||
export default App; | ||
``` | ||
```js | ||
// pages/_document.js | ||
import { Html, Head, Main, NextScript } from 'next/document'; | ||
import { getThemeScript } from 'react-next-theme'; | ||
--- | ||
export default function Document() { | ||
return ( | ||
<Html lang="en"> | ||
<Head> | ||
<link rel="stylesheet" href="/theme.css" /> | ||
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} /> | ||
</Head> | ||
<body> | ||
<Main /> | ||
<NextScript /> | ||
</body> | ||
</Html> | ||
); | ||
} | ||
``` | ||
## Usage in **Next.js (Pages Router)** | ||
- **Option B: Use an external script file**: | ||
### 1. Inject Theme Script in `_document.js` | ||
1. Create `public/theme-script.js`: | ||
To prevent the white flash, you need to inject the theme initialization script using Next.js' `_document.js` file: | ||
```js | ||
// public/theme-script.js | ||
(function() { | ||
const storedTheme = localStorage.getItem('theme'); | ||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||
const theme = storedTheme || (prefersDark ? 'dark' : 'light'); | ||
document.documentElement.setAttribute('data-theme', theme); | ||
})(); | ||
``` | ||
```js | ||
// pages/_document.js | ||
import { Html, Head, Main, NextScript } from 'next/document'; | ||
import { getThemeScript } from 'react-next-theme'; | ||
2. Reference the script file in `_document.js`: | ||
export default function Document() { | ||
return ( | ||
<Html> | ||
<Head> | ||
{/* Inject the theme initialization script */} | ||
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} /> | ||
</Head> | ||
<body> | ||
<Main /> | ||
<NextScript /> | ||
</body> | ||
</Html> | ||
); | ||
} | ||
``` | ||
```js | ||
// pages/_document.js | ||
import { Html, Head, Main, NextScript } from 'next/document'; | ||
import Script from 'next/script'; | ||
### 2. Wrap Your App with `ThemeProvider` in `_app.js` | ||
export default function Document() { | ||
return ( | ||
<Html lang="en"> | ||
<Head> | ||
<link rel="stylesheet" href="/theme.css" /> | ||
</Head> | ||
<body> | ||
<Script src="/theme-script.js" strategy="beforeInteractive" /> | ||
<Main /> | ||
<NextScript /> | ||
</body> | ||
</Html> | ||
); | ||
} | ||
``` | ||
```js | ||
// pages/_app.js | ||
import { ThemeProvider } from 'react-next-theme'; | ||
2. **Wrap Your App with `ThemeProvider` in `_app.js`** | ||
function MyApp({ Component, pageProps }) { | ||
return ( | ||
<ThemeProvider> | ||
<Component {...pageProps} /> | ||
</ThemeProvider> | ||
); | ||
} | ||
Wrap the main component with `ThemeProvider` to handle theme switching: | ||
export default MyApp; | ||
``` | ||
```js | ||
// pages/_app.js | ||
import { ThemeProvider } from 'react-next-theme'; | ||
### 3. Use `useTheme` Hook in Components | ||
function MyApp({ Component, pageProps }) { | ||
return ( | ||
<ThemeProvider> | ||
<Component {...pageProps} /> | ||
</ThemeProvider> | ||
); | ||
} | ||
```js | ||
// components/Header.js | ||
import { useTheme } from 'react-next-theme'; | ||
export default MyApp; | ||
``` | ||
function Header() { | ||
const { theme, toggleTheme } = useTheme(); | ||
--- | ||
return ( | ||
<header> | ||
<button onClick={toggleTheme}> | ||
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'} | ||
</button> | ||
</header> | ||
); | ||
} | ||
## Next.js (App Router) Setup | ||
export default Header; | ||
``` | ||
1. **Theme Initialization in `app/layout.js`** | ||
--- | ||
In Next.js 13+ (App Router), you can initialize the theme by either using `getThemeScript` or an external script file. | ||
## Usage in **Next.js (App Router)** | ||
- **Option A: Use `getThemeScript` directly**: | ||
### 1. Inject Theme Script in `layout.js` | ||
```js | ||
// app/layout.js | ||
import { ThemeProvider, getThemeScript } from 'react-next-theme'; | ||
For **Next.js 13** (App Router), modify the **`app/layout.js`** file to inject the theme initialization script: | ||
export const metadata = { | ||
title: 'My App', | ||
}; | ||
```js | ||
// app/layout.js | ||
import { getThemeScript } from 'react-next-theme'; | ||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<head> | ||
<link rel="stylesheet" href="/theme.css" /> | ||
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} /> | ||
</head> | ||
<body> | ||
<ThemeProvider>{children}</ThemeProvider> | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
export const metadata = { | ||
title: 'My App', | ||
}; | ||
- **Option B: Use an external script file**: | ||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<head> | ||
{/* Inject the theme initialization script */} | ||
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} /> | ||
</head> | ||
<body> | ||
{children} | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
1. Create `public/theme-script.js` as follows: | ||
### 2. Wrap the App with `ThemeProvider` | ||
```js | ||
// public/theme-script.js | ||
(function() { | ||
const storedTheme = localStorage.getItem('theme'); | ||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||
const theme = storedTheme || (prefersDark ? 'dark' : 'light'); | ||
document.documentElement.setAttribute('data-theme', theme); | ||
})(); | ||
``` | ||
In **Next.js (App Router)**, wrap your entire app with the `ThemeProvider`: | ||
2. Reference the script file in `app/layout.js`: | ||
```js | ||
// app/layout.js | ||
import { ThemeProvider } from 'react-next-theme'; | ||
```js | ||
// app/layout.js | ||
import { ThemeProvider } from 'react-next-theme'; | ||
import Script from 'next/script'; | ||
export default function RootLayout({ children }) { | ||
return ( | ||
<ThemeProvider> | ||
{children} | ||
</ThemeProvider> | ||
); | ||
} | ||
``` | ||
export const metadata = { | ||
title: 'My App', | ||
}; | ||
### 3. Use `useTheme` Hook in Components | ||
export default function RootLayout({ children }) { | ||
return ( | ||
<html lang="en"> | ||
<head> | ||
<link rel="stylesheet" href="/theme.css" /> | ||
</head> | ||
<body> | ||
<Script src="/theme-script.js" strategy="beforeInteractive" /> | ||
<ThemeProvider>{children}</ThemeProvider> | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
--- | ||
## Using the `useTheme` Hook to Toggle Themes | ||
To toggle themes in components, use the `useTheme` hook. | ||
```js | ||
@@ -269,2 +313,4 @@ // components/Header.js | ||
{theme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'} | ||
</button> | ||
@@ -277,13 +323,24 @@ </header> | ||
``` | ||
--- | ||
## Using a Script File Instead of Inlining the Script | ||
### **Recommendation** | ||
For simplicity and a clean setup, **using `getThemeScript` is often the best choice**, especially for projects where ease of integration and minimal file management are priorities. It’s also ideal for teams that prefer not to have extra files in `public` or are working on smaller projects. | ||
However, for **larger projects or production-level apps** where caching and modularity are important, **using `public/theme-script.js`** can improve load times slightly and centralize your theme logic. | ||
In summary: | ||
- **Smaller projects or simpler setups** → `getThemeScript` | ||
- **Larger projects or production-focused apps** → `public/theme-script.js` | ||
Let me know if you’d like further customization in setup based on these considerations! | ||
### Using a Script File Instead of Inlining the Script | ||
If you prefer to use an external script file, you can place the theme initialization script inside the **`public/`** folder and reference it using the `<Script>` component in Next.js: | ||
### 1. Create `public/react-next-theme-script.js`: | ||
### 1. Create `public/theme-script.js`: | ||
```js | ||
// public/react-next-theme-script.js | ||
// public/theme-script.js | ||
(function() { | ||
@@ -302,3 +359,3 @@ const storedTheme = localStorage.getItem('theme'); | ||
<Script src="/react-next-theme-script.js" strategy="beforeInteractive" /> | ||
<Script src="/theme-script.js" strategy="beforeInteractive" /> | ||
``` | ||
@@ -305,0 +362,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12742
371