kobalte
kobalte copied to clipboard
No mention of Color Mode Script & dark / light mode handling on the website ?
Describe the bug As describe in the title, I don't find mention about any dark / light mode handling on the website anymore. Is that normal ?
Expected behavior The website should specify how to handle dark / light mode.
Found this strange too when troubleshooting
This is the example mentioned on the shadcn-solid website, however I am having bugs currently
import { ColorModeProvider, ColorModeScript } from "@kobalte/core";
import { MetaProvider } from "@solidjs/meta";
import { Router } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start";
import { Suspense } from "solid-js";
import { isServer } from "solid-js/web";
import { getCookie } from "vinxi/http";
export default function App() {
return (
<Router
root={props => (
<MetaProvider>
<Suspense>
<ColorModeScript />
<ColorModeProvider>{props.children}</ColorModeProvider>
</Suspense>
</MetaProvider>
)}
>
<FileRoutes />
</Router>
);
}
that could help
import { HiOutlineMoon, HiOutlineSun } from "solid-icons/hi";
import { Show } from "solid-js";
import { Button } from "./button";
import { useTheme } from "./theme/theme-provider-context";
const iconWidth = 24;
const ModeToggle = () => {
const { theme, setNextTheme } = useTheme();
return (
<Button variant="ghost" onClick={setNextTheme}>
<Show when={theme() === "light"}>
Light theme
<HiOutlineSun width={iconWidth} />
</Show>
<Show when={theme() === "dark"}>
Dark theme
<HiOutlineMoon width={iconWidth} />
</Show>
<Show when={theme() === "system"}>
System theme
<HiOutlineSun width={iconWidth} />
<HiOutlineMoon width={iconWidth} />
</Show>
</Button>
);
};
export default ModeToggle;
import {
createContext,
createEffect,
createSignal,
ParentProps,
useContext,
} from "solid-js";
type Theme = "light" | "dark" | "system";
const themeKey = "theme_key";
const order: Theme[] = ["light", "dark", "system"];
const ThemeContext = createContext<{
theme: () => Theme;
setNextTheme: () => void;
}>();
export const ThemeProvider = (
props: {
initialTheme?: Theme;
} & ParentProps,
) => {
const [theme, setTheme] = createSignal<Theme>(
props.initialTheme ||
(localStorage.getItem(themeKey) as Theme) ||
props.initialTheme ||
"system",
);
createEffect(() => {
const currentTheme = theme();
const isDark =
currentTheme === "system"
? window.matchMedia("(prefers-color-scheme: dark)").matches
: currentTheme === "dark";
document.documentElement.classList[isDark ? "add" : "remove"]("dark");
localStorage.setItem(themeKey, currentTheme);
});
const setNextTheme = () => {
setTheme(order[(order.indexOf(theme()) + 1) % order.length] as Theme);
};
return (
<ThemeContext.Provider value={{ theme, setNextTheme }}>
{props.children}
</ThemeContext.Provider>
);
};
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
};