Theme management with Solid
I would like to have a Dark and Light Mode on my page. For this I use Solid in combination with Astro.
How would you proceed now?
My current status is that I have created a wrapper object "Scaffold" on the Astro page.
Scaffold is a solidjs component which looks like this:
There I import a "signal" for the theme:
<html> <!-- index.astro -->
<body>
<Scaffold client:only>
<Header client:load />
<main>
<slot />
</main>
<Footer />
</Scaffold>
</body>
</html><html> <!-- index.astro -->
<body>
<Scaffold client:only>
<Header client:load />
<main>
<slot />
</main>
<Footer />
</Scaffold>
</body>
</html>How would you proceed now?
My current status is that I have created a wrapper object "Scaffold" on the Astro page.
Scaffold is a solidjs component which looks like this:
// Scaffold.tsx
import { Component, ErrorBoundary, JSX, Suspense } from "solid-js";
import { createThemeSignal } from "../../theme";
export interface ScaffoldProps {
children?: JSX.Element | JSX.Element[];
}
export const Scaffold: Component<ScaffoldProps> = (props: ScaffoldProps) => {
const [theme] = createThemeSignal();
return <div class="scaffold" data-theme={theme()}>
<Suspense fallback={<div>Loading...</div>}>
<ErrorBoundary fallback={err => <div>Errored: {err}</div>}>
{props.children}
</ErrorBoundary>
</Suspense>
</div>
};// Scaffold.tsx
import { Component, ErrorBoundary, JSX, Suspense } from "solid-js";
import { createThemeSignal } from "../../theme";
export interface ScaffoldProps {
children?: JSX.Element | JSX.Element[];
}
export const Scaffold: Component<ScaffoldProps> = (props: ScaffoldProps) => {
const [theme] = createThemeSignal();
return <div class="scaffold" data-theme={theme()}>
<Suspense fallback={<div>Loading...</div>}>
<ErrorBoundary fallback={err => <div>Errored: {err}</div>}>
{props.children}
</ErrorBoundary>
</Suspense>
</div>
};There I import a "signal" for the theme:
// theme.ts
import { createStore } from "solid-js/store";
export enum Theme {
Light = "light",
Dark = "dark"
}
interface StoreProps {
theme?: Theme | "system"
}
export function createThemeSignal() {
const [store, setStore] = createStore({} as StoreProps);
if (!document.documentElement.hasAttribute("data-theme")) {
document.documentElement.setAttribute("data-theme", store.theme ?? "system");
}
let setTheme = (theme: Theme | "system") => {
document.documentElement.setAttribute("data-theme", theme);
setStore({ theme });
}
let getTheme = () => {
return store.theme ?? "system";
}
return [getTheme, setTheme] as const;
}// theme.ts
import { createStore } from "solid-js/store";
export enum Theme {
Light = "light",
Dark = "dark"
}
interface StoreProps {
theme?: Theme | "system"
}
export function createThemeSignal() {
const [store, setStore] = createStore({} as StoreProps);
if (!document.documentElement.hasAttribute("data-theme")) {
document.documentElement.setAttribute("data-theme", store.theme ?? "system");
}
let setTheme = (theme: Theme | "system") => {
document.documentElement.setAttribute("data-theme", theme);
setStore({ theme });
}
let getTheme = () => {
return store.theme ?? "system";
}
return [getTheme, setTheme] as const;
}