- Downgraded Tailwind CSS to version 3.4.17 for compatibility. - Updated various dependencies to resolve version conflicts and ensure smooth operation. - Added missing types for Node.js to enhance type safety. - Improved the theming system using CSS custom properties (variables) for better customization and dark mode support. - Refactored styles in `app.css` to improve maintainability and readability. Updated the color palette to enhance the user experience. - Updated the PostCSS configuration to use the new Tailwind CSS version. - Updated component styles to utilize the new theming system.
105 lines
2.8 KiB
Svelte
105 lines
2.8 KiB
Svelte
<script lang="ts" module>
|
|
import { createContext } from "../create-context";
|
|
|
|
// Define theme types
|
|
export type Theme = "light" | "dark" | "system";
|
|
|
|
// Create theme context
|
|
export const { get: getThemeContext, set: setThemeContext } =
|
|
createContext<{
|
|
theme: Theme;
|
|
setTheme: (theme: Theme) => void;
|
|
subscribe?: (callback: (theme: Theme) => void) => () => void;
|
|
}>();
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import { onMount } from "svelte";
|
|
|
|
// Props
|
|
export let initialTheme: Theme = "system";
|
|
|
|
// State with reactivity
|
|
let theme = initialTheme;
|
|
let mounted = false;
|
|
|
|
// Create a custom store for the theme
|
|
const themeStore = {
|
|
subscribe: (callback: (theme: Theme) => void) => {
|
|
// Initial call
|
|
callback(theme);
|
|
|
|
// Setup a MutationObserver to watch for class changes on documentElement
|
|
const observer = new MutationObserver(() => {
|
|
callback(theme);
|
|
});
|
|
|
|
observer.observe(document.documentElement, {
|
|
attributes: true,
|
|
attributeFilter: ["class"],
|
|
});
|
|
|
|
// Return unsubscribe function
|
|
return () => observer.disconnect();
|
|
},
|
|
};
|
|
|
|
// Set the theme in localStorage and update the DOM
|
|
function setTheme(newTheme: Theme) {
|
|
theme = newTheme;
|
|
|
|
if (mounted) {
|
|
updateTheme(theme);
|
|
localStorage.setItem("theme", theme);
|
|
}
|
|
}
|
|
|
|
// Update the DOM based on the current theme
|
|
function updateTheme(currentTheme: Theme) {
|
|
const isDark =
|
|
currentTheme === "dark" ||
|
|
(currentTheme === "system" &&
|
|
window.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
|
|
document.documentElement.classList.toggle("dark", isDark);
|
|
}
|
|
|
|
// Initialize theme on mount
|
|
onMount(() => {
|
|
// Get stored theme or use system preference
|
|
const storedTheme = localStorage.getItem("theme") as Theme | null;
|
|
if (storedTheme) {
|
|
theme = storedTheme;
|
|
}
|
|
|
|
// Set up system theme change listener
|
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
const handleChange = () => {
|
|
if (theme === "system") {
|
|
updateTheme("system");
|
|
}
|
|
};
|
|
|
|
mediaQuery.addEventListener("change", handleChange);
|
|
|
|
// Apply initial theme
|
|
updateTheme(theme);
|
|
mounted = true;
|
|
|
|
return () => {
|
|
mediaQuery.removeEventListener("change", handleChange);
|
|
};
|
|
});
|
|
|
|
// Set the context with the store
|
|
setThemeContext({
|
|
get theme() {
|
|
return theme;
|
|
},
|
|
setTheme,
|
|
subscribe: themeStore.subscribe,
|
|
});
|
|
</script>
|
|
|
|
<slot />
|