Skip to content

Commit 3a5680d

Browse files
authored
Merge pull request #6 from react18-tools/fix/5-add-nonce
Add support for Content Security Policy
2 parents 90c4619 + 110c916 commit 3a5680d

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,33 @@ The `nextjs-themes` library was initially created to achieve a similar functiona
1111
## Features
1212

1313
- ✅ Simple API to toggle between dark and light modes
14+
1415
- ✅ Perfect dark mode with just 2 lines of code
15-
- ✅ Compatible with Tailwind CSS
16+
17+
- ✅ Compatible with Tailwind CSS, StyledComponents, emotion, Material UI, ...
18+
19+
- ✅ Secure by design - we support `nonce` when you want to apply Content Security Policy
20+
1621
- ✅ Fully treeshakable (e.g., `import from nextjs-darkmode/hooks`)
22+
1723
- ✅ Full TypeScript support
24+
1825
- ✅ Utilizes React 18 Server components
26+
1927
- ✅ Compatible with all React 18 build systems/tools/frameworks
28+
2029
- ✅ System setting with `prefers-color-scheme`
30+
2131
- ✅ Supports Next.js 13 & 14 `appDir`
32+
2233
- ✅ No flash on load (supports SSG, SSR, ISG, and Server Components)
34+
2335
- ✅ Sync theme across tabs and windows
36+
2437
- ✅ Apply custom transitions when changing themes
38+
2539
- ✅ Manipulate theme via the `useMode` hook
40+
2641
- ✅ No cookies when not using the corresponding `ServerTarget`
2742

2843
- ✅ Comprehensive documentation with [Typedoc](https://react18-tools.github.io/nextjs-darkmode)
@@ -190,6 +205,14 @@ When using `ServerTarget`, use the CSS general sibling combinator (~):
190205

191206
`data-sm` -> System preference
192207

208+
#### Content Security Policy
209+
210+
If you are using CSP rules for CSS files, you can pass `nonce` argument to the `Core` component. If `nonce` is not supplied transition styles will not be applied. This may allow patched transitions throught the page in some cases.
211+
212+
```tsx
213+
<Core nonce={yourNonce} t="transition: all .5s" />
214+
```
215+
193216
### Images
194217

195218
Show different images based on the current theme:

lib/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# nextjs-darkmode
22

3+
## 0.1.0
4+
5+
### Minor Changes
6+
7+
- Add nonce to support Content Security Policy
8+
39
## 0.0.3
410

511
### Patch Changes

lib/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "nextjs-darkmode",
33
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
44
"private": false,
5-
"version": "0.0.3",
5+
"version": "0.1.0",
66
"description": "Unleash the Power of React Server Components! Use dark/light mode on your site with confidence, without losing any advantages of React Server Components",
77
"license": "MPL-2.0",
88
"main": "./dist/index.js",
@@ -97,6 +97,10 @@
9797
"Server Components",
9898
"Dark Mode",
9999
"React18 Tools",
100+
"Content Security Policy",
101+
"Security",
102+
"CSP",
103+
"nonce",
100104
"Themes",
101105
"Customizable",
102106
"UI Components",

lib/src/client/core/core.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import { useEffect } from "react";
55
export interface CoreProps {
66
/** force apply CSS transition property to all the elements during theme switching. E.g., `all .3s` */
77
t?: string;
8+
/** The nonce value for your Content Security Policy. */
9+
nonce?: string;
810
}
911

1012
/** Modify transition globally to avoid patched transitions */
11-
const modifyTransition = (themeTransition = "none") => {
13+
const modifyTransition = (themeTransition = "none", nonce = "") => {
1214
const css = document.createElement("style");
1315
/** split by ';' to prevent CSS injection */
1416
css.textContent = `*{transition:${themeTransition.split(";")[0]} !important;}`;
17+
nonce && css.setAttribute("nonce", nonce);
1518
document.head.appendChild(css);
1619

1720
return () => {
@@ -33,7 +36,7 @@ const modifyTransition = (themeTransition = "none") => {
3336
*
3437
* @source - Source code
3538
*/
36-
export const Core = ({ t }: CoreProps) => {
39+
export const Core = ({ t, nonce }: CoreProps) => {
3740
const [{ m: mode, s: systemMode }, setThemeState] = useStore();
3841
const resolvedMode = mode === SYSTEM ? systemMode : mode; // resolvedMode is the actual mode that will be used
3942

@@ -58,7 +61,7 @@ export const Core = ({ t }: CoreProps) => {
5861
}, []);
5962

6063
useEffect(() => {
61-
const restoreTransitions = modifyTransition(t);
64+
const restoreTransitions = modifyTransition(t, nonce);
6265
const serverTargetEl = document.querySelector("[data-ndm]");
6366
// We need to always update documentElement to support Tailwind configuration
6467
// skipcq: JS-D008, JS-0042 -> map keyword is shorter
@@ -79,7 +82,7 @@ export const Core = ({ t }: CoreProps) => {
7982
localStorage.setItem(COOKIE_KEY, mode);
8083
if (serverTargetEl)
8184
document.cookie = `${COOKIE_KEY}=${resolvedMode};max-age=31536000;SameSite=Strict;`;
82-
}, [resolvedMode, systemMode, mode, t]);
85+
}, [resolvedMode, systemMode, mode, t, nonce]);
8386

8487
return null;
8588
};

packages/shared/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @repo/shared
22

3+
## 0.0.4
4+
5+
### Patch Changes
6+
7+
- Updated dependencies
8+
9+
310
## 0.0.3
411

512
### Patch Changes

packages/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@repo/shared",
3-
"version": "0.0.3",
3+
"version": "0.0.4",
44
"private": true,
55
"sideEffects": false,
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)