From f609b10ab3e871cfc7c5fd99d7936d8ea2b7f58d Mon Sep 17 00:00:00 2001 From: ankitsejwal Date: Mon, 29 Jun 2026 01:42:03 +0530 Subject: [PATCH 1/2] Add theme store and no-flash boot script --- apps/web/index.html | 8 ++++++++ apps/web/src/stores/theme-store.ts | 30 ++++++++++++++++++++++++++++++ apps/web/src/styles.css | 2 ++ 3 files changed, 40 insertions(+) create mode 100644 apps/web/src/stores/theme-store.ts diff --git a/apps/web/index.html b/apps/web/index.html index 4cbc928..83f0ea6 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -7,6 +7,14 @@ Polaroid — print-at-home photo frames +
diff --git a/apps/web/src/stores/theme-store.ts b/apps/web/src/stores/theme-store.ts new file mode 100644 index 0000000..1d603d9 --- /dev/null +++ b/apps/web/src/stores/theme-store.ts @@ -0,0 +1,30 @@ +import { create } from 'zustand' + +export type Theme = 'light' | 'dark' + +// The initial class is set by an inline script in index.html (before paint), +// so we just read it back here to seed the store. +function currentTheme(): Theme { + if (typeof document === 'undefined') return 'light' + return document.documentElement.classList.contains('dark') ? 'dark' : 'light' +} + +interface ThemeState { + theme: Theme + setTheme: (theme: Theme) => void + toggle: () => void +} + +export const useThemeStore = create((set, get) => ({ + theme: currentTheme(), + setTheme: (theme) => { + document.documentElement.classList.toggle('dark', theme === 'dark') + try { + localStorage.setItem('theme', theme) + } catch { + // Private mode / storage disabled — the choice just won't persist. + } + set({ theme }) + }, + toggle: () => get().setTheme(get().theme === 'dark' ? 'light' : 'dark'), +})) diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index d840f32..9a66256 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -4,6 +4,7 @@ @custom-variant dark (&:is(.dark *)); :root { + color-scheme: light; --radius: 0.625rem; --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); @@ -24,6 +25,7 @@ } .dark { + color-scheme: dark; --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); --card: oklch(0.205 0 0); From 65663373db5051138dcff55bd58f423ded8edd01 Mon Sep 17 00:00:00 2001 From: ankitsejwal Date: Mon, 29 Jun 2026 01:42:03 +0530 Subject: [PATCH 2/2] Add header light/dark toggle --- apps/web/src/components/theme-toggle.tsx | 32 ++++++++++++++++++++++++ apps/web/src/routes/index.tsx | 6 ++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/components/theme-toggle.tsx diff --git a/apps/web/src/components/theme-toggle.tsx b/apps/web/src/components/theme-toggle.tsx new file mode 100644 index 0000000..d19ed59 --- /dev/null +++ b/apps/web/src/components/theme-toggle.tsx @@ -0,0 +1,32 @@ +import { Moon, Sun } from 'lucide-react' + +import { Button } from '@/components/ui/button' +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/ui/tooltip' +import { useThemeStore } from '@/stores/theme-store' + +export function ThemeToggle() { + const theme = useThemeStore((state) => state.theme) + const toggle = useThemeStore((state) => state.toggle) + const dark = theme === 'dark' + + return ( + + + + + {dark ? 'Light mode' : 'Dark mode'} + + ) +} diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx index b4b71a9..55ce00f 100644 --- a/apps/web/src/routes/index.tsx +++ b/apps/web/src/routes/index.tsx @@ -4,6 +4,7 @@ import { A4Preview } from '@/components/a4-preview' import { OptionsPanel } from '@/components/options-panel' import { PhotoSidebar } from '@/components/photo-sidebar' import { ProjectControls } from '@/components/project-controls' +import { ThemeToggle } from '@/components/theme-toggle' export const Route = createFileRoute('/')({ component: Home, @@ -19,7 +20,10 @@ function Home() { Edit each frame on the page — everything stays on your device.

- +
+ + +