I have a nextjs 13 application and I'm using Clerk for authentication.
I'm trying to match the theme of the app to the ClerkProvider
component.
I used the useTheme
hook from next-themes
to get the resolvedTheme
and assign the theme accordingly, but that required converting the layout.tsx
into a client component which misses up with the metadata. I'm wondering if there is a better way to handle this.
Here is my code:
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ClerkProvider } from "@clerk/nextjs";
import { ThemeProvider } from "@/components/theme-provider";
import { useTheme } from "next-themes";
import { dark } from "@clerk/themes";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const { resolvedTheme } = useTheme();
return (
<ClerkProvider
appearance={{
baseTheme: resolvedTheme === "dark" ? dark : undefined,
}}
>
<html lang="en" suppressHydrationWarning>
<body className={inter.className}>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
</ClerkProvider>
);
}
Rather than setting it from Clerk → ThemeProvider, I suggest to do it the other way round.
As mentioned in the answer by Ahmad Mughal, you won't be able to set the appearance in the ClerkProvider globally, since it's expected to run only on the server.
You can however set the appearance on the level of Clerk components where you can use useTheme()
(if you declare the page a client component with 'use client').
A page like this will render the appearance of the Clerk SignIn component according to the current theme from the ThemeProvider:
"use client";
import { SignIn } from "@clerk/nextjs";
import { dark } from "@clerk/themes";
import { useTheme } from "next-themes";
const PageWithSignIn = () => {
const { currentTheme } = useTheme();
return (
<SignIn
appearance={{
baseTheme: currentTheme === "dark" ? dark : undefined,
}}
/>
);
};
export default Page;