diff --git a/apps/start/src/components/theme-provider.tsx b/apps/start/src/components/theme-provider.tsx index 5b5a4c84..1a4b2388 100644 --- a/apps/start/src/components/theme-provider.tsx +++ b/apps/start/src/components/theme-provider.tsx @@ -1,5 +1,6 @@ +import { useCookieStore } from '@/hooks/use-cookie-store'; import { mapKeys } from '@openpanel/validation'; -import { ScriptOnce } from '@tanstack/react-router'; +import { ScriptOnce, useRouteContext } from '@tanstack/react-router'; import { createIsomorphicFn } from '@tanstack/react-start'; import { type ReactNode, createContext, use, useEffect, useState } from 'react'; import { z } from 'zod'; @@ -115,7 +116,10 @@ type ThemeProviderProps = { children: ReactNode; }; export function ThemeProvider({ children }: ThemeProviderProps) { - const [userTheme, setUserTheme] = useState(getStoredUserTheme); + const [userTheme, setUserTheme] = useCookieStore( + 'ui-theme', + 'system', + ); useEffect(() => { if (userTheme !== 'system') return; diff --git a/apps/start/src/hooks/use-cookie-store.tsx b/apps/start/src/hooks/use-cookie-store.tsx index 032f3636..360bc3a8 100644 --- a/apps/start/src/hooks/use-cookie-store.tsx +++ b/apps/start/src/hooks/use-cookie-store.tsx @@ -1,11 +1,14 @@ import { useRouteContext } from '@tanstack/react-router'; import { createServerFn, createServerOnlyFn } from '@tanstack/react-start'; import { getCookies, setCookie } from '@tanstack/react-start/server'; +import { pick } from 'ramda'; import { useMemo, useState } from 'react'; import { z } from 'zod'; +const VALID_COOKIES = ['ui-theme', 'chartType', 'range'] as const; + const setCookieFn = createServerFn({ method: 'POST' }) - .inputValidator(z.object({ key: z.string(), value: z.string() })) + .inputValidator(z.object({ key: z.enum(VALID_COOKIES), value: z.string() })) .handler(({ data: { key, value } }) => { setCookie(key, value); }); @@ -13,10 +16,13 @@ const setCookieFn = createServerFn({ method: 'POST' }) // Called in __root.tsx beforeLoad hook to get cookies from the server // And recieved with useRouteContext in the client export const getCookiesFn = createServerFn({ method: 'GET' }).handler(() => - getCookies(), + pick(VALID_COOKIES, getCookies()), ); -export function useCookieStore(key: string, defaultValue: T) { +export function useCookieStore( + key: (typeof VALID_COOKIES)[number], + defaultValue: T, +) { const { cookies } = useRouteContext({ strict: false }); const [value, setValue] = useState((cookies?.[key] ?? defaultValue) as T); diff --git a/apps/start/src/routes/__root.tsx b/apps/start/src/routes/__root.tsx index 869277a5..46b5a68c 100644 --- a/apps/start/src/routes/__root.tsx +++ b/apps/start/src/routes/__root.tsx @@ -80,6 +80,11 @@ function RootDocument({ children }: { children: React.ReactNode }) { + + + {children} + +