secureweb/sweb/src/lib/theme/ThemeProvider.svelte
Mahmoud Emad f22e9faae2 chore: Update Tailwind CSS and dependencies
- 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.
2025-05-12 13:47:47 +03:00

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 />