feat: Add nuqs to apply theme from query param initially

This commit is contained in:
Sahaj Jain
2025-04-09 23:16:43 +05:30
parent cea1ffe4b5
commit da7a3d896d
6 changed files with 78 additions and 22 deletions
+1
View File
@@ -59,6 +59,7 @@
"lucide-react": "^0.483.0",
"motion": "^12.5.0",
"next-themes": "^0.3.0",
"nuqs": "^2.4.1",
"posthog-js": "^1.232.4",
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
+33
View File
@@ -149,6 +149,9 @@ importers:
next-themes:
specifier: ^0.3.0
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
nuqs:
specifier: ^2.4.1
version: 2.4.1(react-router@7.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
posthog-js:
specifier: ^1.232.4
version: 1.234.9
@@ -2731,6 +2734,9 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
motion-dom@12.6.3:
resolution: {integrity: sha512-gRY08RjcnzgFYLemUZ1lo/e9RkBxR+6d4BRvoeZDSeArG4XQXERSPapKl3LNQRu22Sndjf1h+iavgY0O4NrYqA==}
@@ -2801,6 +2807,24 @@ packages:
resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
nuqs@2.4.1:
resolution: {integrity: sha512-u6sngTspqDe3jWHtcmqHQg3dl35niizCZAsm5gy7PBlgG2rwl71Dp2QUv5hwBaWKI9qz0wqILZY86TsRxq66SQ==}
peerDependencies:
'@remix-run/react': '>=2'
next: '>=14.2.0'
react: '>=18.2.0 || ^19.0.0-0'
react-router: ^6 || ^7
react-router-dom: ^6 || ^7
peerDependenciesMeta:
'@remix-run/react':
optional: true
next:
optional: true
react-router:
optional: true
react-router-dom:
optional: true
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -5840,6 +5864,8 @@ snapshots:
minipass@7.1.2: {}
mitt@3.0.1: {}
motion-dom@12.6.3:
dependencies:
motion-utils: 12.6.3
@@ -5907,6 +5933,13 @@ snapshots:
npm-package-arg: 10.1.0
semver: 7.7.1
nuqs@2.4.1(react-router@7.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
dependencies:
mitt: 3.0.1
react: 18.3.1
optionalDependencies:
react-router: 7.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
object-assign@4.1.1: {}
object-hash@3.0.0: {}
+24 -21
View File
@@ -9,6 +9,7 @@ import Home from "./pages/home";
import { lazy, Suspense } from "react";
import { Loading } from "./components/loading";
import { HelmetProvider } from "react-helmet-async";
import { NuqsAdapter } from "nuqs/adapters/react-router/v7";
const Index = lazy(() => import("@/pages/index"));
@@ -18,27 +19,29 @@ const options = {
};
const App = () => (
<ThemeProvider defaultTheme="light">
<PostHogProvider
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}
options={options}
>
<QueryClientProvider client={queryClient}>
<HelmetProvider>
<TooltipProvider>
<Toaster />
<Sonner />
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/editor/theme" element={<Index />} />
</Routes>
</Suspense>
</TooltipProvider>
</HelmetProvider>
</QueryClientProvider>
</PostHogProvider>
</ThemeProvider>
<NuqsAdapter>
<ThemeProvider defaultTheme="light">
<PostHogProvider
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}
options={options}
>
<QueryClientProvider client={queryClient}>
<HelmetProvider>
<TooltipProvider>
<Toaster />
<Sonner />
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/editor/theme" element={<Index />} />
</Routes>
</Suspense>
</TooltipProvider>
</HelmetProvider>
</QueryClientProvider>
</PostHogProvider>
</ThemeProvider>
</NuqsAdapter>
);
export default App;
@@ -2,7 +2,6 @@ import { ThemeEditorPreviewProps } from "@/types/theme";
import { Tabs, TabsContent, TabsList } from "@/components/ui/tabs";
import { ScrollArea, ScrollBar } from "../ui/scroll-area";
import ColorPreview from "./theme-preview/color-preview";
import ComponentsShowcase from "./theme-preview/components-showcase";
import TabsTriggerPill from "./theme-preview/tabs-trigger-pill";
import ExamplesPreviewContainer from "./theme-preview/examples-preview-container";
import { lazy } from "react";
+4
View File
@@ -4,6 +4,7 @@ import { colorFormatter } from "../utils/color-converter";
import { setShadowVariables } from "@/utils/shadows";
import { applyStyleToElement } from "@/utils/apply-style-to-element";
import { ThemeStyleProps, ThemeStyles } from "@/types/theme";
import { useThemePresetFromUrl } from "@/hooks/use-theme-preset-from-url";
type Theme = "dark" | "light";
@@ -80,6 +81,9 @@ const updateThemeClass = (root: HTMLElement, mode: Theme) => {
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
const { themeState, setThemeState } = useEditorStore();
// Handle theme preset from URL
useThemePresetFromUrl();
useLayoutEffect(() => {
const root = window.document.documentElement;
const { currentMode: mode, styles: themeStyles } = themeState;
+16
View File
@@ -0,0 +1,16 @@
import { useQueryState } from "nuqs";
import React from "react";
import { useEditorStore } from "@/store/editor-store";
export const useThemePresetFromUrl = () => {
const [preset, setPreset] = useQueryState("theme");
const applyThemePreset = useEditorStore((state) => state.applyThemePreset);
// Apply theme preset if it exists in URL and remove it
React.useEffect(() => {
if (preset) {
applyThemePreset(preset);
setPreset(null); // Remove the preset from URL
}
}, [preset, setPreset, applyThemePreset]);
};