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

Support for theme-color #78

Open
shuding opened this issue Jan 6, 2022 · 21 comments · Fixed by #114
Open

Support for theme-color #78

shuding opened this issue Jan 6, 2022 · 21 comments · Fixed by #114
Labels
enhancement New feature or request v1 Planned for v1

Comments

@shuding
Copy link
Contributor

shuding commented Jan 6, 2022

Safari 15 uses this meta tag to indicate the UI color of the address bar etc., and usually we need to switch it upon theme changes. The media query only works with the system preferences rather than per-site settings via next-themes, so it might be a good add-on for this lib to automatically update it.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color

@pacocoursey
Copy link
Owner

pacocoursey commented Jan 6, 2022

You can set theme-color to a CSS variable, which will update correctly on Safari! On iOS it will update instantly alongside changes to the CSS variable, on macOS it will only update when you refocus the tab.

<meta name="theme-color" content="var(--bg)">

If we were to add it to next-themes (and not use the CSS variable trick above), how we would determine which color to set? Maybe consumers could provide a --theme-color CSS variable, which next-themes would read the current value of (getComputedStyle) and update the meta tag accordingly.

@shuding
Copy link
Contributor Author

shuding commented Jan 7, 2022

Oh I didn’t know that it works with variables, then it almost solves my problem.

If building this into the lib, I can see a themeColor option with these possible values:

  • themeColor: { dark: '#000', light: '#fff' }: provide the theme color for each theme
  • themeColor: 'red': always use this theme color
  • themeColor: 'var(—-bg)': if using a variable, we can compute the color upon every theme change. The variable needs to be specified at the root level
  • themeColor: { dark: 'var(—-bg)', reduced: '#fff' }: mixed use case too

@pacocoursey pacocoursey added the enhancement New feature or request label Feb 1, 2022
@pacocoursey pacocoursey added the v1 Planned for v1 label Feb 20, 2022
@nifte
Copy link

nifte commented Feb 22, 2022

@pacocoursey Using the meta tag method you mentioned doesn't seem to be working in the latest Safari/iOS. I still need to refresh the page to see the browser theme change.

I'm setting the css variable like this (I use class mode with Tailwind):

html { --bg: white; }
html.dark { --bg: black; }

Any suggestions?

@heychazza
Copy link

Facing the same thing myself.

@pacocoursey
Copy link
Owner

Since the CSS variable trick no longer seems to work, I'd recommend implementing this manually in your code with something like this:

const { resolvedTheme } = useTheme();

return (
  <Head>
    <meta name="theme-color" value={resolvedTheme === 'dark' ? '#000' : '#fff'}
  </Head>
)

I plan to add this for v1 of next-themes though, and I like the API that @shuding suggested above!

<ThemeProvider
  themeColor={{ dark: '#000', light: '#fff' }}
  // or
  themeColor="var(--theme-color)" // vars must be on the same element as data-theme is applied, which right is now always html aka :root
  // or
  themeColor={{ dark: 'var(--dark-bg)', light: '#fff' }}
/>

@pacocoursey
Copy link
Owner

pacocoursey commented May 17, 2022

This is available in the v1 beta:

yarn add next-themes@beta

@EryouHao
Copy link

Hi @pacocoursey , when v1 release? like this feature.

@AdisonCavani
Copy link

@pacocoursey v1 is not published on NPM.

@aulianza
Copy link

i solve this problem using this approach:

const { resolvedTheme } = useTheme();

  useEffect(() => {
    let themeColorMeta = document.querySelector(
      'meta[name="theme-color"]',
    ) as HTMLMetaElement;

    if (!themeColorMeta) {
      themeColorMeta = document.createElement('meta');
      themeColorMeta.name = 'theme-color';
      document.head.appendChild(themeColorMeta);
    }

    themeColorMeta.content = resolvedTheme === 'dark' ? '#171717' : '#fff';
  }, [resolvedTheme]);

may this help!

@NavOrange
Copy link

For Next.js 13 app router

app/layout.tsx

export const metadata = {
  // ...
  themeColor: '#f8fafc',
}

export default RootLayout() {
  <html suppressHydrationWarning className="dark">
    <head>
        <script
          dangerouslySetInnerHTML={{
            __html: `
              try {
                if (localStorage.theme === 'dark' || ((!('theme' in localStorage) || localStorage.theme === 'system') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
                  document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0B1120')
                }
              } catch (_) {}
            `,
          }}
        />
      </head>
  </html>
}

components/toggle-theme.tsx

const { resolvedTheme } = useTheme()

useEffect(() => {
  if (resolvedTheme === 'dark') {
    document
      .querySelector('meta[name="theme-color"]')!
      .setAttribute('content', '#0B1120')
  } else {
    document
      .querySelector('meta[name="theme-color"]')!
      .setAttribute('content', '#f8fafc')
  }
}, [resolvedTheme])

refer https://github.com/tailwindlabs/tailwindcss.com/blob/master/src/pages/_document.js#L31

@shawnlong636
Copy link

Is a fix being worked on for this so we don’t need to add custom logic to ensure automatic color switching on Safari?

@trm217
Copy link
Collaborator

trm217 commented Aug 28, 2023

@shawnlong636 Could you elaborate? Do you have the issue with the v1 branch?

@alex-grover
Copy link

confirming this is working for me with the 1.0.0-beta.0 release

is there any plan to release that as a full version? happy to help test, it looks like the changes are fairly small

@theonlyway
Copy link

Any timeline on when v1 will be released?

@spacecat
Copy link

spacecat commented Mar 14, 2024

This one did not make it to v0.3.0? 🤔
I'm still targeting the beta in my project ( "next-themes": "1.0.0-beta.0", ) which is not ideal. Hoping to see v1 soon! Or just this particular very needed feature in v0.3.1 😉

@pacocoursey
Copy link
Owner

Planning to add this in v1, which is still upcoming.

@monecchi
Copy link

monecchi commented Jun 15, 2024

@pacocoursey Hi there! How to achieve the proposed themeColor solution? I've installed next-themes@beta, current version 0.3.0-beta.1, but it seems <ThemeProvider /> has no themeColor props.

@spacecat
Copy link

spacecat commented Jun 23, 2024

@monecchi you can do something like this:

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider
      attribute="class"
      themes={[
        "light",
        "dark",
      ]}
      themeColor={{
        light: "hsl(0 0% 100%)",
        dark: "hsl(216 13% 15%)",
      }}
    >
      <SidebarLeftMobileProvider>
        <SidebarRightMobileProvider>
           <UserProvider>{children}</UserProvider>
        </SidebarRightMobileProvider>
      </SidebarLeftMobileProvider>
    </ThemeProvider>
  );
}

I'm using "next-themes": "1.0.0-beta.0",

@monecchi
Copy link

Thanks @spacecat! I'll give it a try! It seems the beta version I installed 0.3.0-beta.1 might be the issue...

Also, thanks @NavOrange! I've tested your solution and it worked flawlessly! While developing a PWA with the Window Controls Overlay feature enabled in manifest.json (on Desktop), the window native controls background color inherits the theme-color value, so switching the theme (light / dark) was breaking the UI. That saved my day!

@spacecat
Copy link

@spacecat yes, most likely it has got to do with the npm package version.

@spacecat
Copy link

spacecat commented Nov 28, 2024

Hi @pacocoursey ,

just following up on this issue as I'm currently upgrading all of my npm packages in my project.

I was just wondering if you see this feature included in a stable release some time in the near future?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request v1 Planned for v1
Projects
None yet
Development

Successfully merging a pull request may close this issue.