-
-
Notifications
You must be signed in to change notification settings - Fork 214
Add option to opt-out of automatic script insertion #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add option to opt-out of automatic script insertion #353
Conversation
Co-authored-by: Steven <[email protected]>
…lmrry/next-themes into plmrry/add-script-document-head-option
@@ -32,6 +32,7 @@ export const ThemeProvider = (props: ThemeProviderProps) => { | |||
const defaultThemes = ['light', 'dark'] | |||
|
|||
const Theme = ({ | |||
withScript = true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new prop that allows us to bypass mounting the script when set to false
}} | ||
/> | ||
|
||
{withScript ? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here's where withScript
determines if we should mount the script
{children} | ||
</ThemeContext.Provider> | ||
) | ||
} | ||
|
||
const ThemeScript = React.memo( | ||
export const ThemeScript = React.memo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export ThemeScript
for manual placement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this id necessary? We already have scriptProps
@styfle I removed that unnecessary |
document.documentElement.removeAttribute('data-theme-test') | ||
document.documentElement.removeAttribute('data-example') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is un-related, but I noticed these need to be removed
Co-authored-by: Steven <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks! 🎉
@pacocoursey Can you take another look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this, the PR looks quite succinct now. However I'm not sure this is a good approach – you're basically adding a feature that allows consumers to shoot themselves in the foot and not have perfect dark mode as this library advertises.
Could you elaborate on the issues you experienced with flashing on Chrome? Is this due to the script not being injected in the <head>
element? If so, ideally the library can be fixed to inject into the head instead by using next/link
with beforeHydration
option. This way everyone that uses it will have correct behavior out of the box –– the whole point of this library.
In the past, next/script
was quite buggy and this option didn't work reliably. But that was 2+ years ago so maybe it's viable to do it again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback.
To be honest, this PR is just relaying work by @cramforce that was done internally. I need to dig into the original bug a bit more.
If so, ideally the library can be fixed to inject into the head instead by using next/link with beforeHydration option.
Would this mean adding next
as a dependency? Happy to do this if that's what you mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, it'd be helpful to know more about the root issue. And yes, we can bring back next
as a peerDep. It is next-themes
, after all.
But we could also offer the option to export the script standalone as this PR already does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pacocoursey I'm working on a repro of the original issue, but in the meantime I created a tiny PR to export <ThemeScript>
:
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:
withScript
prop to<Theme>
.<ThemeScript>
by settingwithScript
tofalse
.withScript
defaults 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
id
prop that gets added to the script itselfExample
This is pseudo-code:
Based on internal work from @cramforce: