Skip to content
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

Option to respect system theme preference changes after setTheme has been called #164

Open
jasongerbes opened this issue Jan 25, 2023 · 2 comments

Comments

@jasongerbes
Copy link

Currently, next-themes has two exclusive behaviours:

  1. Respect system theme preference changes, i.e. set theme based on device preference.
  2. Respect the theme set via setTheme from the useTheme() hook.

If the theme has been set using setTheme, the application's theme will no longer be automatically updated when the system's theme changes, e.g. if the user's device changes from dark mode to light mode.

It would be great if you could add the option to always respect system theme preference changes, even after setTheme has been called, for example:

Step Theme
1. Application opened with 'light mode' system theme 'light'
2. Call setTheme('dark') 'dark'
3. System theme changes to 'dark mode' 'dark'
4. System theme changes to 'light mode' 'light'

A good example of this behaviour is the dark/light mode toggle on @joshwcomeau's blog:
https://www.joshwcomeau.com

This also seems to be the default behaviour of the useDarkMode package (unmaintained):

Changing the system dark mode state will also change the state of useDarkMode (i.e, change to light mode in the system will change to light mode in your app).

Workaround

A workaround is to manually call setTheme('system') when the device theme changes:

const { setTheme } = useTheme();

const handleSystemThemeChange = useCallback(() => setTheme('system'), [setTheme]);

// Copied from src/index.tsx
useEffect(() => {
  const media = window.matchMedia('(prefers-color-scheme: dark)');

  // Intentionally use deprecated listener methods to support iOS & old browsers
  media.addListener(handleSystemThemeChange);

  return () => media.removeListener(handleSystemThemeChange);
}, [handleSystemThemeChange]);

Or by using the provided systemTheme value:

const { systemTheme, setTheme } = useTheme();

useEffect(() => {
  setTheme('system')
}, [systemTheme, setTheme]);

The problem with these workarounds is the theme is always reverted to the system them when reloading the application.

@6abotage
Copy link

6abotage commented Feb 7, 2023

@pacocoursey I think this would be a great addition. What do you think about it?
If you think you and the community would welcome it and you would merge an implementation of this feature I would try to implement it

@TomPichaud
Copy link

Maybe another option would be to set the theme back to default & respect user's preference if it matches with the selected theme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants