Skip to content

Commit 365fdbc

Browse files
author
designcise
committed
docs: updated docs to reflect changes for localStorage
1 parent c252eb0 commit 365fdbc

File tree

1 file changed

+31
-50
lines changed

1 file changed

+31
-50
lines changed

README.md

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
# next-theme-toggle
22

3-
This package is based on [https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js](https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js).
3+
A simple theme toggle for Next.js 13+ that allows switching between light and dark themes. Using this package would result in the following `class` and `style` attributes added to the `<html>` element:
44

5-
## Goals
5+
```html
6+
<html class="dark" style="color-scheme:dark">
7+
```
68

7-
The goal of the project is to:
9+
You can then [use different CSS selectors to create styles for dark/light themes](https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js#switching-theme).
10+
11+
## Goals
812

913
- Provide an easy way of toggling between light and dark themes
1014
- Auto-switch theme on page load based on system settings
1115
- Avoid flicker on page load
1216
- Have no unnecessary bloat
1317
- Have very minimal configuration
14-
15-
## Expectations
16-
17-
Result of using this package will be that the following are added to the `<html>` element:
18-
19-
```html
20-
<html class="dark" style="color-scheme:dark">
21-
```
22-
23-
After which you can [use different CSS selectors to create styles for dark/light themes](https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js#switching-theme).
18+
- Be simple and intuitive
2419

2520
## Installation
2621

@@ -43,7 +38,7 @@ $ yarn add @designcise/next-theme-toggle
4338

4439
## Quickstart
4540

46-
> **NOTE**: Please note that this approach relies on using cookies on client and server side, and will, therefore, cause the route to be dynamically rendered as cookies rely on request time information.
41+
> **NOTE**: Please note that this approach relies on using `localStorage` on the client side to store theme information.
4742
4843
At a bare minimum you need to do the following:
4944

@@ -55,48 +50,26 @@ import { cookies } from 'next/headers';
5550
import { Html, ThemeProvider } from '@designcise/next-theme-toggle';
5651
import { getColors } from '@designcise/next-theme-toggle/server';
5752

58-
// 1: specify key for cookie storage
53+
// 1: specify key for storage
5954
const THEME_STORAGE_KEY = 'theme-preference';
6055
const color = getColors();
6156

6257
export default async function RootLayout() {
63-
// 2.1: get the user theme preference value from cookie, if one exists
64-
// 2.2: set a default value in case the cookie doesn't exist (e.g. `?? color.light`)
65-
const theme = cookies().get(THEME_STORAGE_KEY)?.value ?? color.light;
66-
67-
// 3.1: use the `Html` component to prevent flicker
68-
// 3.2: wrap components with `ThemeProvider` to pass theme down to all components
58+
// 2: wrap components with `ThemeProvider` to pass theme props down to all components
59+
// 3: pass `storageKey` and (optional) `defaultTheme` to `ThemeProvider`
6960
return (
70-
<Html theme={theme}>
61+
<html>
7162
<body>
72-
<ThemeProvider storageKey={THEME_STORAGE_KEY} theme={theme}>
63+
<ThemeProvider storageKey={THEME_STORAGE_KEY} defaultTheme={color.dark}>
7364
{children}
7465
</ThemeProvider>
7566
</body>
76-
</Html>
67+
</html>
7768
)
7869
}
7970
```
8071

81-
The `Html` component is added for convenience. If you do not wish to use it, then you can achieve the same with the native `html` element in the following way:
82-
83-
```jsx
84-
// replace:
85-
<Html theme={theme}>
86-
87-
// with:
88-
<html className={theme} style={{ colorScheme: theme }}>
89-
```
90-
91-
You may also choose to not do this step altogether and pass `autoAntiFlicker={true}` (or just `autoAntiFlicker`) to the `ThemeProvider` component, which will automatically inject a script into DOM that takes care of this for you. For example:
92-
93-
```jsx
94-
<ThemeProvider storageKey={THEME_STORAGE_KEY} theme={theme} autoAntiFlicker>
95-
```
96-
97-
All these approaches help you avoid flicker on initial page load.
98-
99-
> **NOTE**: Please note that using the script injection method will show the `Warning: Extra attributes from the server: class,style` warning in console in the dev environment only. This is unavoidable unfortunately, as it happens because the injected script adds additional `class` and `style` attributes to the `html` element which do not originally exist on the server-side generated page.
72+
With this setup, the `ThemeProvider` component will automatically inject an inline script into DOM that takes care of avoiding flicker on initial page load.
10073

10174
2. Create a button to toggle between light and dark theme:
10275

@@ -204,12 +177,11 @@ That's it! You should have light/dark theme toggle in your Next.js application.
204177

205178
You can pass the following props to `ThemeProvider`:
206179

207-
| Prop | Type | Description |
208-
|-------------------|:--------------------------------------------:|:------------------------------------------------------------:|
209-
| `children` | `React.ReactChild`&vert;`React.ReactChild[]` | Components to which the theme is passed down to via context. |
210-
| `storageKey` | String | Name of the key used for storage. |
211-
| `theme` | String | Starting theme; can be `'light'` or `'dark'`. |
212-
| `autoAntiFlicker` | Boolean | If `true`, injects an inline anti-flicker script to DOM. |
180+
| Prop | Type | Description |
181+
|----------------|:--------------------------------------------:|:------------------------------------------------------------------:|
182+
| `children` | `React.ReactChild`&vert;`React.ReactChild[]` | Components to which the theme is passed down to via context. |
183+
| `storageKey` | String | Name of the key used for storage. |
184+
| `defaultTheme` | String | Default theme (`'light'` or `'dark'`) to use on initial page load. |
213185

214186
### `useTheme()`
215187

@@ -231,7 +203,7 @@ Returns an object, with the following:
231203
| `light` | String | `'light'` | Color value used for light theme. |
232204
| `theme` | String | `'dark'`. | Color value used for dark theme. |
233205

234-
> **NOTE**: The `getColors()` function can be used in both, the client components and server components.
206+
> **NOTE**: The `getColors()` function can be used in both, client components and server components.
235207
236208
For server components you can import `getColors()` like so:
237209

@@ -296,10 +268,19 @@ To fix this, you can add the folder where your CSS or SASS file is located. For
296268
// ...
297269
```
298270

271+
#### `Warning: Extra attributes from the server: class,style` in Console
272+
273+
This warning _only_ shows on dev build and _not_ in the production build. This happens because the injected script adds _additional_ `class` and `style` attributes to the `html` element which _do not_ originally exist on the server-side generated page, leading to a mismatch in the server-side and client-side rendered page.
274+
299275
## Contributing
300276

301277
https://github.com/designcise/next-theme-toggle/blob/main/CONTRIBUTING.md
302278

303279
## License
304280

305281
https://github.com/designcise/next-theme-toggle/blob/main/LICENSE.md
282+
283+
## Resources
284+
285+
- [https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js](https://www.designcise.com/web/tutorial/how-to-create-non-flickering-dark-or-light-mode-toggle-in-next-js).
286+

0 commit comments

Comments
 (0)