mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-06 04:22:07 +00:00
start working version of new theme handler
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Select, { type SelectOption } from './Select.svelte';
|
||||
import { Select as Select2 } from '$lib/components/ui';
|
||||
import { themeStore, setTheme, type Theme } from '$lib/providers/theme';
|
||||
import { get } from 'svelte/store';
|
||||
import { themeStore, setTheme } from '$lib/providers/theme';
|
||||
|
||||
const options = [
|
||||
{
|
||||
@@ -28,6 +27,6 @@
|
||||
{options}
|
||||
bind:value={$themeStore.theme}
|
||||
onValueChange={(e) => {
|
||||
setTheme(e as Theme);
|
||||
setTheme(e);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<div {...select.content}>
|
||||
{#each options as option}
|
||||
<div {...select.getOption(option.value)}>
|
||||
{option}
|
||||
{option.label}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export type Theme = 'dark' | 'light' | 'system';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export interface ThemeStore {
|
||||
themes: string[];
|
||||
forcedTheme?: Theme;
|
||||
theme?: Theme;
|
||||
resolvedTheme?: string;
|
||||
systemTheme?: Omit<Theme, 'system'>;
|
||||
}
|
||||
export interface ThemeStore {
|
||||
themes: string[];
|
||||
forcedTheme?: string;
|
||||
theme?: string;
|
||||
resolvedTheme?: string;
|
||||
systemTheme?: string;
|
||||
}
|
||||
|
||||
export const setTheme = (theme?: Theme): void =>
|
||||
themeStore.update((store) => ({ ...store, theme }));
|
||||
|
||||
export const themeStore = writable<ThemeStore>({
|
||||
themes: [],
|
||||
forcedTheme: undefined,
|
||||
theme: undefined,
|
||||
resolvedTheme: undefined,
|
||||
systemTheme: undefined
|
||||
});
|
||||
// Create the theme store
|
||||
export const themeStore = writable<ThemeStore>({
|
||||
themes: ['light', 'dark'],
|
||||
forcedTheme: undefined,
|
||||
theme: undefined,
|
||||
resolvedTheme: undefined,
|
||||
systemTheme: undefined
|
||||
});
|
||||
|
||||
|
||||
export { default as ThemeProvider } from './theme.svelte'
|
||||
export const setTheme = (theme?: string) =>
|
||||
themeStore.update((store) => ({ ...store, theme }));
|
||||
|
||||
export const setResolvedTheme = (resolvedTheme?: string) =>
|
||||
themeStore.update((store) => ({ ...store, resolvedTheme }));
|
||||
|
||||
export const setSystemTheme = (systemTheme?: string) =>
|
||||
themeStore.update((store) => ({ ...store, systemTheme }));
|
||||
|
||||
export const setThemes = (themes: string[]) =>
|
||||
themeStore.update((store) => ({ ...store, themes }));
|
||||
|
||||
export { default as ThemeProvider } from './theme.svelte';
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { colorSchemes, MEDIA } from './constants';
|
||||
import { disableAnimation, getSystemTheme, getTheme } from './helpers';
|
||||
import { themeStore, setTheme, type Theme } from './index';
|
||||
import { themeStore, setTheme } from './index';
|
||||
|
||||
import ThemeScript from './theme-script.svelte';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
interface Props {
|
||||
forcedTheme?: Theme;
|
||||
forcedTheme?: string;
|
||||
disableTransitionOnChange?: boolean;
|
||||
enableSystem?: boolean;
|
||||
enableColorScheme?: boolean;
|
||||
storageKey?: string;
|
||||
themes?: string[];
|
||||
defaultTheme?: Theme;
|
||||
defaultTheme?: string;
|
||||
attribute?: string | 'class';
|
||||
value?: {
|
||||
[themeName: string]: string;
|
||||
@@ -51,13 +51,14 @@
|
||||
const attrs = !value ? themes : Object.values(value);
|
||||
|
||||
const handleMediaQuery = (e?: MediaQueryList) => {
|
||||
const systemTheme = getSystemTheme(e) as Theme;
|
||||
const systemTheme = getSystemTheme(e) as string;
|
||||
$themeStore.resolvedTheme = systemTheme;
|
||||
$themeStore.systemTheme = systemTheme;
|
||||
|
||||
if (theme === 'system' && !forcedTheme) changeTheme(systemTheme, false);
|
||||
if (theme === 'system' && !forcedTheme) changeTheme(systemTheme, false, true);
|
||||
};
|
||||
|
||||
const changeTheme = (theme?: Theme, updateStorage?: boolean, updateDOM?: boolean) => {
|
||||
const changeTheme = (theme?: string, updateStorage?: boolean, updateDOM?: boolean) => {
|
||||
if (!theme) return;
|
||||
let name = value?.[theme] || theme;
|
||||
|
||||
@@ -77,7 +78,7 @@
|
||||
}
|
||||
|
||||
if (updateDOM && browser) {
|
||||
const d = document.documentElement;
|
||||
const d = document.body;
|
||||
|
||||
if (attribute === 'class') {
|
||||
d.classList.remove(...(attrs as string[]));
|
||||
@@ -93,20 +94,20 @@
|
||||
|
||||
const storageHandler = (e: StorageEvent) => {
|
||||
if (e.key !== storageKey) return;
|
||||
setTheme((e.newValue as Theme) || (defaultTheme as Theme));
|
||||
setTheme((e.newValue as string) || (defaultTheme as string));
|
||||
};
|
||||
|
||||
const onWindow = (window: Window) => {
|
||||
const media = window.matchMedia(MEDIA);
|
||||
// Intentionally use deprecated listener methods to support iOS & old browsers
|
||||
media.addListener(mediaHandler);
|
||||
// Use modern event listener approach
|
||||
media.addEventListener('change', mediaHandler);
|
||||
mediaHandler(media);
|
||||
|
||||
window.addEventListener('storage', storageHandler);
|
||||
return {
|
||||
destroy() {
|
||||
window.removeEventListener('storage', storageHandler);
|
||||
media.removeListener(mediaHandler);
|
||||
media.removeEventListener('change', mediaHandler);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -133,7 +134,7 @@
|
||||
if (forcedTheme) {
|
||||
changeTheme(theme, true, false);
|
||||
} else {
|
||||
changeTheme(theme);
|
||||
changeTheme(theme, true, true); // Add true for updateDOM parameter
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
>
|
||||
|
||||
<slot />
|
||||
<ThemeProvider />
|
||||
<ThemeProvider attribute="class" disableTransitionOnChange />
|
||||
|
||||
<style lang="scss">
|
||||
:global(html) {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { Config } from 'tailwindcss';
|
||||
|
||||
const config = {} satisfies Config;
|
||||
|
||||
export default config;
|
||||
Reference in New Issue
Block a user