38 lines
1.3 KiB
TypeScript
38 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
|
|
import { useProjects } from "@/components/projects/projects-context";
|
|
import { useThemeScope } from "./theme-provider";
|
|
|
|
/**
|
|
* Temporarily scopes the app's theme (see ThemeProvider in
|
|
* theme-provider.tsx) to the project's assigned theme while that project's
|
|
* page is on screen. The theme lifts the moment you navigate away, so the
|
|
* rest of the app (Home, other projects) keeps the user's global
|
|
* preference.
|
|
*
|
|
* The theme is read from the live ProjectsContext -- not a page prop -- so
|
|
* picking a new theme in the picker transforms the page *immediately*,
|
|
* without waiting for the server re-render after the action settles.
|
|
* `null` (the "Default theme" state) is a no-op: the page follows the
|
|
* global theme, and changing the global theme from the theme menu while on
|
|
* the page takes effect here too.
|
|
*
|
|
* The provider never learns the preference from this component (the global
|
|
* `theme` state and localStorage are untouched).
|
|
*/
|
|
export function ProjectThemeScope({ projectId }: { projectId: string }) {
|
|
const { projects } = useProjects();
|
|
const { setScope } = useThemeScope();
|
|
|
|
const theme = projects.find((p) => p.id === projectId)?.theme ?? null;
|
|
|
|
useEffect(() => {
|
|
setScope(theme);
|
|
return () => setScope(null);
|
|
}, [theme, setScope]);
|
|
|
|
return null;
|
|
}
|