Skip to content

Commit 5c0947c

Browse files
feat: allow overriding theme via url theme param
1 parent 6c45d0d commit 5c0947c

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

typescript-sdk/apps/dojo/src/app/layout.tsx

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Metadata } from "next";
33
import { Geist, Geist_Mono } from "next/font/google";
44
import "./globals.css";
55
import "@copilotkit/react-ui/styles.css";
6-
import { ThemeProvider } from "@/components/theme-provider";
6+
import { ThemeWrapper } from "@/components/theme-wrapper";
77
import { MainLayout } from "@/components/layout/main-layout";
88
import { URLParamsProvider } from "@/contexts/url-params-context";
99

@@ -30,19 +30,13 @@ export default function RootLayout({
3030
return (
3131
<html lang="en" suppressHydrationWarning>
3232
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
33-
<ThemeProvider
34-
attribute="class"
35-
defaultTheme="light"
36-
enableSystem={false}
37-
themes={['light']}
38-
disableTransitionOnChange
39-
>
40-
<Suspense>
41-
<URLParamsProvider>
33+
<Suspense>
34+
<URLParamsProvider>
35+
<ThemeWrapper>
4236
<MainLayout>{children}</MainLayout>
43-
</URLParamsProvider>
44-
</Suspense>
45-
</ThemeProvider>
37+
</ThemeWrapper>
38+
</URLParamsProvider>
39+
</Suspense>
4640
</body>
4741
</html>
4842
);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client";
2+
3+
import { ThemeProvider } from "@/components/theme-provider";
4+
import { useURLParams } from "@/contexts/url-params-context";
5+
6+
export function ThemeWrapper({ children }: { children: React.ReactNode }) {
7+
const { theme } = useURLParams();
8+
9+
return (
10+
<ThemeProvider
11+
attribute="class"
12+
forcedTheme={theme}
13+
enableSystem={false}
14+
themes={["light", "dark"]}
15+
disableTransitionOnChange
16+
>
17+
{children}
18+
</ThemeProvider>
19+
);
20+
}
21+

typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface URLParamsState {
1313
featurePickerHidden: boolean;
1414
file?: string;
1515
codeLayout: "sidebar" | "tabs";
16+
theme: "light" | "dark";
1617
}
1718

1819
interface URLParamsContextType extends URLParamsState {
@@ -24,6 +25,7 @@ interface URLParamsContextType extends URLParamsState {
2425
setFeaturePickerHidden: (disabled: boolean) => void;
2526
setCodeFile: (fileName: string) => void;
2627
setCodeLayout: (layout: "sidebar" | "tabs") => void;
28+
setTheme: (theme: "light" | "dark") => void;
2729
}
2830

2931
const URLParamsContext = createContext<URLParamsContextType | undefined>(undefined);
@@ -46,6 +48,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
4648
viewPickerHidden: searchParams.get("viewPicker") === "false",
4749
featurePickerHidden: searchParams.get("featurePicker") === "false",
4850
codeLayout: (searchParams.get("codeLayout") as "sidebar" | "tabs") || "sidebar",
51+
theme: (searchParams.get("theme") as "light" | "dark") || "light",
4952
}));
5053

5154
// Update URL when state changes
@@ -114,6 +117,15 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
114117
}
115118
}
116119

120+
// Update theme param
121+
if (newState.theme !== undefined) {
122+
if (newState.theme === "light") {
123+
params.delete("theme");
124+
} else {
125+
params.set("theme", newState.theme);
126+
}
127+
}
128+
117129
// Update file param
118130
if (newState.file !== undefined) {
119131
params.set("file", newState.file);
@@ -134,6 +146,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
134146
featurePickerHidden: searchParams.get("featurePicker") === "false",
135147
file: searchParams.get("file") || undefined,
136148
codeLayout: (searchParams.get("codeLayout") as "sidebar" | "tabs") || "sidebar",
149+
theme: (searchParams.get("theme") as "light" | "dark") || "light",
137150
};
138151

139152
setState(newState);
@@ -188,6 +201,12 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
188201
updateURL({ codeLayout });
189202
};
190203

204+
const setTheme = (theme: "light" | "dark") => {
205+
const newState = { ...state, theme };
206+
setState(newState);
207+
updateURL({ theme });
208+
};
209+
191210
const contextValue: URLParamsContextType = {
192211
...state,
193212
setView,
@@ -198,6 +217,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) {
198217
setFeaturePickerHidden,
199218
setCodeFile,
200219
setCodeLayout,
220+
setTheme,
201221
};
202222

203223
return <URLParamsContext.Provider value={contextValue}>{children}</URLParamsContext.Provider>;

0 commit comments

Comments
 (0)