Add option to opt-out of automatic script insertion
Problem
We've seen a bug in Chrome where (in dark mode) there is a flash of light-themed code.
This appears to be due to how next-themes inserts <ThemeScript /> into the <body />
Solution
This PR:
- Adds an optional
withScriptprop to<Theme>.
- This allows the user to optionally disable the insertion of
<ThemeScript>by settingwithScripttofalse. -
withScriptdefaults totrue, which preserves the default behavior ofnext-themes.
-
Exports
<ThemeScript>, so it can be manually inserted by the user (i.e. in the<head>) -
Adds an optional string
idprop that gets added to the script itself
Example
This is pseudo-code:
import { ThemeProvider, ThemeScript } from 'next-themes'
export default function RootLayout({
children
}): JSX.Element {
return (
<html>
<head>
<ThemeScript storageKey="my-theme" />
</head>
<body>
<ThemeProvider storageKey="my-theme" withScript={false}>
{children}
</body>
</html>
)
}
Based on internal work from @cramforce:
This appears to fix a long-standing bug where you get a flash of light-theme in Chrome.
The primary change in the fork is to allow placing the inline script manually. With the default-usage of next-themes, the script always goes into the body (usually first).
@styfle I removed that unnecessary id prop and added a unit test