Files
ProjectE/apps/web/src/components/shell/theme-provider.tsx
T
Hermes e86a7c0672 T5/Phase 3: SPA shell + navigation
- TanStack Router with type-safe file-based routes
- Sidebar: collapsible, workspace switcher, 12 nav links, user menu
- Topbar: search, quick-add, notifications, user avatar
- cmdk command palette: nav + create + search + @mentions
- Keyboard shortcuts: Cmd+K palette, g+t/h/p/n/c/g/s navigation, ? help
- Theme: dark default, accent picker (slate/blue/green/purple/orange), persisted to localStorage
- Auth: login -> /, logout -> /login, 401 redirect
- Placeholder pages for all 13 nav routes (real in T6/T7)
- Typed API client with useApiQuery/useApiMutation hooks
2026-08-01 02:00:24 +00:00

33 lines
1.1 KiB
TypeScript

import { useEffect } from "react";
import { useThemeStore, ACCENT_PALETTE, type AccentColor } from "@/lib/stores/use-theme-store";
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const { mode, accent } = useThemeStore();
useEffect(() => {
const root = document.documentElement;
// Apply dark/light mode
if (mode === "system") {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handler = (e: MediaQueryListEvent | MediaQueryList) => {
root.classList.toggle("dark", e.matches);
};
handler(mediaQuery);
mediaQuery.addEventListener("change", handler as (e: MediaQueryListEvent) => void);
return () =>
mediaQuery.removeEventListener("change", handler as (e: MediaQueryListEvent) => void);
} else {
root.classList.toggle("dark", mode === "dark");
}
}, [mode]);
useEffect(() => {
const root = document.documentElement;
const palette = ACCENT_PALETTE[accent as AccentColor] || ACCENT_PALETTE.blue;
root.style.setProperty("--accent-hsl", palette.hsl);
}, [accent]);
return <>{children}</>;
}