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

Force page to a theme with Next 13 app dir #187

Open
waraness99 opened this issue Jun 28, 2023 · 6 comments
Open

Force page to a theme with Next 13 app dir #187

waraness99 opened this issue Jun 28, 2023 · 6 comments

Comments

@waraness99
Copy link

How can we force a specific page to a theme using Next 14 app dir?

Since there is no more _app file, how can i do this using layout?

/pages/awesome-page.js

const Page = () => { ... }
Page.theme = 'dark'
export default Page

_app

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider forcedTheme={Component.theme || null}>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}
@KimboTodd
Copy link

Is this what you're looking for? https://github.com/pacocoursey/next-themes#with-app

@waraness99
Copy link
Author

no i already have this implementation. i'm looking for a way to force dark mode on a specific page with this app dir implementation. the provided example only works with page dir, because inside layout we can only access children and not Component or pageProps

@subhamBharadwaz
Copy link

no i already have this implementation. i'm looking for a way to force dark mode on a specific page with this app dir implementation. the provided example only works with page dir, because inside layout we can only access children and not Component or pageProps

Did you find any solution?

@bradenhilton
Copy link

bradenhilton commented Jul 12, 2023

A decent (but imperfect) solution would be to check the pathname against known values. Something like this:

'use client';

import { usePathname } from 'next/navigation';
import { ThemeProvider } from 'next-themes';
import { ThemeProviderProps } from 'next-themes/dist/types';

const getPageTheme = (pathname: string): ThemeProviderProps['forcedTheme'] => {
  // Add pathnames without a '/' prefix here.
  // '' matches the homepage.
  const darkModePages = ['', 'test'];
  const lightModePages = ['test2'];

  // Exact matches, more strict
  if (
    darkModePages.some((name) => pathname === `/${name}`) &&
    lightModePages.some((name) => pathname === `/${name}`)
  ) {
    return;
  }
  if (darkModePages.some((name) => pathname === `/${name}`)) return 'dark';
  if (lightModePages.some((name) => pathname === `/${name}`)) return 'light';

  // Starts with, less strict
  if (
    darkModePages.some((name) => pathname.startsWith(`/${name}`)) &&
    lightModePages.some((name) => pathname.startsWith(`/${name}`))
  ) {
    return;
  }
  if (darkModePages.some((name) => pathname.startsWith(`/${name}`)))
    return 'dark';
  if (lightModePages.some((name) => pathname.startsWith(`/${name}`)))
    return 'light';

  return;
};

export function Providers({ children }: React.PropsWithChildren) {
  const pathname = usePathname();
  return (
    <>
      <ThemeProvider attribute='class' forcedTheme={getPageTheme(pathname)}>
        {children}
      </ThemeProvider>
    </>
  )
}

// "/" -> "dark"
// "/test" -> "dark"
// "/test2" -> "light"
// "/test3" -> "dark"
// "/testing" -> "dark"
// "/about" -> undefined (will use default/system if you have it enabled)

@subhamBharadwaz
Copy link

Thanks. I only wanted my home page to be dark, so :

export function Providers({ children }: ProviderProps) {
  const pathname = usePathname()
  return (
    <ThemeProvider
      forcedTheme={pathname === "/" ? "dark" : null}
      attribute="class"
      defaultTheme="dark"
      enableSystem
    >
    </ThemeProvider>
  )
}

@jamesvclements
Copy link

This solution works great, but what if I need my not-found.js route to force a theme? Should that be the default cause in the switch statement? But then I would need to hard-code every route in my site into the switch statement. Any thoughts?

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

5 participants